현업 SW 개발자의 연구 노트
Hits

모든 콘텐츠 열람

본 웹사이트에 포함된 모든 콘텐츠들을 텍스트로 제공합니다.
Title : 30분 단위 시간 관리 시작
URL : /diary/2024/05/13/30%EB%B6%84-%EB%8B%A8%EC%9C%84-%EC%8B%9C%EA%B0%84%EA%B4%80%EB%A6%AC.html
Description : 2024년 5월 11일 (월요일) 일기
Content : 요약






정말 오랜만의 일기

오늘부터 시간 관리를 30분 단위로 하기로 했다.

30분 단위 시간 관리

식사 이력




구분
메뉴
비고




아침
오뎅볶음 반찬만
집밥


점심
회사 점심밥
 


저녁
부대찌개
집밥




["요약\n\n ✅\n ✅\n ✅\n\n\n정말 오랜만의 일기\n\n오늘부터 시간 관리를 30분 단위로 하기로 했다.\n\n30분 단위 시간 관리\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 오뎅볶음 반찬만\n 집밥\n \n \n 점심\n 회사 점심밥\n  \n \n \n 저녁\n 부대찌개\n 집밥\n \n \n\n\n"]
Title : 성남시 고등동 회식장소 강돈
URL : /diary/2023/11/23/%EC%84%B1%EB%82%A8%EC%8B%9C-%EA%B3%A0%EB%93%B1%EB%8F%99-%EA%B3%A0%EA%B9%83%EC%A7%91-%EA%B0%95%EB%8F%88.html
Description : 2023년 11월 23일 (목요일) 일기
Content : 요약

✅ 회사 소모임으로 강돈에서 식사
✅ 2차로 가마치에 잠깐 들림
✅ 3차로 투다리에서 거하게 마심


정말 오랜만의 일기
정말 오랜만에 일기를 작성해본다.
내 기억들은 곳곳이 흩어져 있다.
네이버 블로그에도 흩어져 있고,
GitHub Pages에도 흩어져 있다.

강돈에서 1차 모임

회사에서 다양한 소모임들을 하고 있다.
그 중에서 요즘 가장 애정하는 소모임이 있다.
비록 청계산 산행은 하지 못했지만, 좋아하는 사람들이랑 술한잔하면서 잘 어울렸다.

새로 알게된 사람들도 제법 있어서 좋았다.

가마치 통닭에서 2차

1차가 파하고 대빵님은 빠르게 퇴장하셨다.
2차로 갔던 곳은 다른 부서 회식장소였다.
다른 부서 회식이 마무리되는 시점이라서 가마치에서는 아무것도 먹지도 못하고 3차 장소로 휩쓸려갔다.

투다리에서 3차

투다리에서 3차를 했다.
소주를 들이킬때까지는 괜찮았는데,
하이볼을 마신 후부터는 술이 급격하게 올라서
와이프 핑계를 대고 귀가를 했다.

식사 이력




구분
메뉴
비고




아침
기억 안남
 


점심
기억 안남
회사 점심밥


저녁
뼈삼겹 구이
강돈




내가 뭘 먹었는지도 잘 기억이 안 난다.

["요약\n\n ✅ 회사 소모임으로 강돈에서 식사\n ✅ 2차로 가마치에 잠깐 들림\n ✅ 3차로 투다리에서 거하게 마심\n\n\n정말 오랜만의 일기\n정말 오랜만에 일기를 작성해본다. \n내 기억들은 곳곳이 흩어져 있다. \n네이버 블로그에도 흩어져 있고, \nGitHub Pages에도 흩어져 있다.\n\n강돈에서 1차 모임\n\n회사에서 다양한 소모임들을 하고 있다. \n그 중에서 요즘 가장 애정하는 소모임이 있다. \n비록 청계산 산행은 하지 못했지만, 좋아하는 사람들이랑 술한잔하면서 잘 어울렸다.\n\n새로 알게된 사람들도 제법 있어서 좋았다.\n\n가마치 통닭에서 2차\n\n1차가 파하고 대빵님은 빠르게 퇴장하셨다. \n2차로 갔던 곳은 다른 부서 회식장소였다. \n다른 부서 회식이 마무리되는 시점이라서 가마치에서는 아무것도 먹지도 못하고 3차 장소로 휩쓸려갔다.\n\n투다리에서 3차\n\n투다리에서 3차를 했다. \n소주를 들이킬때까지는 괜찮았는데, \n하이볼을 마신 후부터는 술이 급격하게 올라서 \n와이프 핑계를 대고 귀가를 했다.\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 기억 안남\n  \n \n \n 점심\n 기억 안남\n 회사 점심밥\n \n \n 저녁\n 뼈삼겹 구이\n 강돈\n \n \n\n\n내가 뭘 먹었는지도 잘 기억이 안 난다.\n\n"]
Title : 장인상 조의에 대한 감사인사를 드렸다.
URL : /diary/2022/12/05/%EC%9E%A5%EC%9D%B8%EC%83%81-%EA%B0%90%EC%82%AC-%EC%9D%B8%EC%82%AC.html
Description : 지난 장인상에 조의를 베풀어주신 회사 동료분들에게 메일로 감사인사를 드렸다.
Content : 감사 인사 올립니다.

저의 장인상에 조의를 베풀어 주셔서 감사합니다.
덕분에 장례를 무사히 치르고 잘 모실 수 있었습니다.

장인께서는 직장아도 췌장암도 극복하셨으나 최근 혈관에 암이 재발하여 항암 치료를 하고 계셨습니다.
투병으로 기력이 쇠하신 상태에서 COVID-19에 확진되셨고 급성 패혈증 쇼크로 운명을 달리하셨습니다.

장인께서는 무뚝뚝하시지만 누구보다도 속정이 깊으신 분이셨습니다.
생전에는 골프, 등산, 자전거, 당구, 탁구 등 다양한 운동을 즐기셨고,
기타, 하모니카, 난타 등을 배우는 것을 즐겼습니다.

바쁘신 와중에도 조의를 베풀어 주셔서 감사합니다.
보내주신 은혜 평생 잊지 않겠습니다.
귀댁의 경사나 애사시에 꼭 연락주시어 베푸신 은혜에 보답하기 원합니다.

OOO 배상
["감사 인사 올립니다.\n\n저의 장인상에 조의를 베풀어 주셔서 감사합니다. \n덕분에 장례를 무사히 치르고 잘 모실 수 있었습니다.\n\n장인께서는 직장아도 췌장암도 극복하셨으나 최근 혈관에 암이 재발하여 항암 치료를 하고 계셨습니다. \n투병으로 기력이 쇠하신 상태에서 COVID-19에 확진되셨고 급성 패혈증 쇼크로 운명을 달리하셨습니다.\n\n장인께서는 무뚝뚝하시지만 누구보다도 속정이 깊으신 분이셨습니다. \n생전에는 골프, 등산, 자전거, 당구, 탁구 등 다양한 운동을 즐기셨고, \n기타, 하모니카, 난타 등을 배우는 것을 즐겼습니다.\n\n바쁘신 와중에도 조의를 베풀어 주셔서 감사합니다. \n보내주신 은혜 평생 잊지 않겠습니다. \n귀댁의 경사나 애사시에 꼭 연락주시어 베푸신 은혜에 보답하기 원합니다.\n\nOOO 배상\n"]
Title : 아버지를 여읜 아내의 불안정한 심리 상태 + 프랭크버거 성남고등점
URL : /diary/2022/12/01/diary.html
Description : 22년 12월 01일 일기
Content : 어제 장인을 경남 창녕에 있는 선산에 모셨다.
아내의 심리 상태는 불안정해 보였다.
가족과 통화하며 훌쩍거리며 울다가도 불같이 화를 내기도 했다.
특히 장례 도중에 친척에게서 입은 상처가 컸다.
다들 마음을 많이 쓰다보니 작은 일에도 마음에 생채기가 났다.



["어제 장인을 경남 창녕에 있는 선산에 모셨다. \n아내의 심리 상태는 불안정해 보였다. \n가족과 통화하며 훌쩍거리며 울다가도 불같이 화를 내기도 했다. \n특히 장례 도중에 친척에게서 입은 상처가 컸다. \n다들 마음을 많이 쓰다보니 작은 일에도 마음에 생채기가 났다.\n\n\n\n"]
Title : 급성 패혈증으로 중환자실에 계신 장인어르신 임종 면회 (서울아산병원)
URL : /diary/2022/11/26/diary.html
Description : 장인어른께서 곧 돌아가실지도 모른다. 모든 기억들을 기록으로 남겨야 한다.
Content : 아파트 놀이터에서 아이들과 놀고 있는데 와이프로부터 전화가 왔다.

와이프가 짧게 말했다. “가자…”

내가 바로 대답했다. “응”

놀이터에서 놀고 있던 아이들을 데리고 급하게 집으로 돌아왔다.
집에 돌아와보니 아내는 아버님을 뵈러 가기 위해 외출복으로 갈아입고 있었다.
두 아들을 어머니에게 맡기고 지하주차장으로 향했다.
아내와 함께 차를 타고 서울아산병원 서관으로 향했다.

병원으로 향하는 차 안에서 아내는 흐느꼈다.
울음을 그치고 안정을 취했다가도 다시 훌쩍거리기를 반복했다.
나는 최대한 운전에 집중하려고 노력했다.
평소와 달리 끼어들기를 여러차례 했다.
그때마다 신경질적으로 비상 깜빡이를 몇초간 작동시켰다.

서울아산병원에 도착했다.
형님 차에서 처형이 슬픈 표정으로 황망히 내렸다.
아내와 처형은 중환자실이 있는 서관쪽으로 급하게 뛰어갔다.
형님과 나는 주차장에 차를 세웠다.

아내와 처형은 임종이 임박한줄로 착각하고 마지막 인사를 했다.
형님과 나도 전화로 장인어른께 인사를 드렸다.

다행히 장인어른께서는 안정을 되찾으셨다.
아내 말로는 장인어른의 상태가 평온해보였다고 한다.
며칠은 더 견딜 수 있을 것같이 보였다고 한다.


["아파트 놀이터에서 아이들과 놀고 있는데 와이프로부터 전화가 왔다.\n\n와이프가 짧게 말했다. “가자…”\n\n내가 바로 대답했다. “응”\n\n놀이터에서 놀고 있던 아이들을 데리고 급하게 집으로 돌아왔다. \n집에 돌아와보니 아내는 아버님을 뵈러 가기 위해 외출복으로 갈아입고 있었다. \n두 아들을 어머니에게 맡기고 지하주차장으로 향했다. \n아내와 함께 차를 타고 서울아산병원 서관으로 향했다.\n\n병원으로 향하는 차 안에서 아내는 흐느꼈다. \n울음을 그치고 안정을 취했다가도 다시 훌쩍거리기를 반복했다. \n나는 최대한 운전에 집중하려고 노력했다. \n평소와 달리 끼어들기를 여러차례 했다. \n그때마다 신경질적으로 비상 깜빡이를 몇초간 작동시켰다.\n\n서울아산병원에 도착했다. \n형님 차에서 처형이 슬픈 표정으로 황망히 내렸다. \n아내와 처형은 중환자실이 있는 서관쪽으로 급하게 뛰어갔다. \n형님과 나는 주차장에 차를 세웠다.\n\n아내와 처형은 임종이 임박한줄로 착각하고 마지막 인사를 했다. \n형님과 나도 전화로 장인어른께 인사를 드렸다.\n\n다행히 장인어른께서는 안정을 되찾으셨다. \n아내 말로는 장인어른의 상태가 평온해보였다고 한다. \n며칠은 더 견딜 수 있을 것같이 보였다고 한다.\n\n\n"]
Title : 와이파이 비밀번호 메모
URL : /it/2022/11/23/%EC%99%80%EC%9D%B4%ED%8C%8C%EC%9D%B4-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8.html
Description : 와이파이 비밀번호를 메모합니다.
Content : 와이파이는 지역적으로만 서비스가 가능합니다.
이 때문에 와이파이에 비밀번호를 설정한다는 것은 큰 의미가 없다고 생각합니다.
카페나 음식점에서 제공되는 와이파이의 경우 실제로 비밀번호를 벽면에 써 두는 경우가 많습니다.
와이파이의 신호를 잡을 수 있는 곳에 있다면, 비밀번호도 충분히 알 수 있습니다.
사실상 비밀번호가 필요없다는게 저의 개인적인 생각입니다.

본 페이지에서는 여러 매장들에 대한 와이파이 비밀번호를 기록해두고자 합니다.




무선랜
PW
상호
비고




KT_GiGA_2G_Wave2_007A
dx47ff4131
진짜부동산
성남시 고등동


KT_GiGA_5G_Wave2_007A
dx47ff4131
진짜부동산
성남시 고등동


교촌치킨고등점
0317541992
교촌치킨 고등점
성남시 고등동


KT-GiGA-18E1
dccf4fg933
좋은아침 페스츄리
성남시 고등동


HSguest
mb3421#@
메르세데스벤츠 분당백현서비스센터
성남시 백현동


EM0119
em4590119
세곡달빛의원
서울시 강남구 세곡동


KT_GiGA_4AE7
fc7fbc8805
마누스케이크
의왕시 학의동


KT_GiGA_5G_4AE7
fc7fbc8805
마누스케이크
의왕시 학의동


KT_GiGA_2G_Wave2_7AAD
ag3fef5530
초야농원
경북 성주군 대가면 금산리


KT_GiGA_5G_Wave2_7AAD
ag3fef5530
초야농원
경북 성주군 대가면 금산리




이상입니다.
["와이파이는 지역적으로만 서비스가 가능합니다. \n이 때문에 와이파이에 비밀번호를 설정한다는 것은 큰 의미가 없다고 생각합니다. \n카페나 음식점에서 제공되는 와이파이의 경우 실제로 비밀번호를 벽면에 써 두는 경우가 많습니다. \n와이파이의 신호를 잡을 수 있는 곳에 있다면, 비밀번호도 충분히 알 수 있습니다.\n사실상 비밀번호가 필요없다는게 저의 개인적인 생각입니다.\n\n본 페이지에서는 여러 매장들에 대한 와이파이 비밀번호를 기록해두고자 합니다.\n\n\n \n \n 무선랜\n PW\n 상호\n 비고\n \n \n \n \n KT_GiGA_2G_Wave2_007A\n dx47ff4131\n 진짜부동산\n 성남시 고등동\n \n \n KT_GiGA_5G_Wave2_007A\n dx47ff4131\n 진짜부동산\n 성남시 고등동\n \n \n 교촌치킨고등점\n 0317541992\n 교촌치킨 고등점\n 성남시 고등동\n \n \n KT-GiGA-18E1\n dccf4fg933\n 좋은아침 페스츄리\n 성남시 고등동\n \n \n HSguest\n mb3421\#@\n 메르세데스벤츠 분당백현서비스센터\n 성남시 백현동\n \n \n EM0119\n em4590119\n 세곡달빛의원\n 서울시 강남구 세곡동\n \n \n KT_GiGA_4AE7\n fc7fbc8805\n 마누스케이크\n 의왕시 학의동\n \n \n KT_GiGA_5G_4AE7\n fc7fbc8805\n 마누스케이크\n 의왕시 학의동\n \n \n KT_GiGA_2G_Wave2_7AAD\n ag3fef5530\n 초야농원\n 경북 성주군 대가면 금산리\n \n \n KT_GiGA_5G_Wave2_7AAD\n ag3fef5530\n 초야농원\n 경북 성주군 대가면 금산리\n \n \n\n\n이상입니다.\n"]
Title : 코스트코 꼬막비빔밥 - 꼬막이 실하게 들어있다 (14,990원)
URL : /costco/2022/11/23/%EC%BD%94%EC%8A%A4%ED%8A%B8%EC%BD%94-%EA%BC%AC%EB%A7%89%EB%B9%84%EB%B9%94%EB%B0%A5.html
Description : 코스트코 꼬막비빔밥은 언제나 OK!
Content : 나는 꼬막비빔밥에 진심이다. :smile:
순천에서 먹었던 꼬막비빔밥은 인상적인 기억으로 남아 있다.
와이프님께서 코스토코엘 다녀왔다.
오늘 저녁은 꼬막비빔밥이라고 했다.
꼬막비빔밥이라면 언제나 OK다!


구입처 : 코스트코
구입일 : 2022년 11월 23일
가격 : 14,990원


코스트코에서 14,990원에 구입했다.
꼬막이 아주 실하게 들어있다.
참기름의 고소한 향과 꼬막의 쫄깃한 식감이 잘 어울린다.

원재료

꼬막 : 38.24%
정제수
쌀 : 18.54%
꼬막비빔밥용소스 : 9.27%
참기름
오이고추

볶음참깨


고소한 참기름 냄새

냉장고를 열어보니 반가운 꼬막 비빔밥이 있었다.
뚜껑을 열어보니 고소한 참기름 냄새가 느껴졌다.


가장자리 부분은 쌀밥이 있었고, 가운데 부분은 꼬막이 있었다.
꼬막은 생각보다 훨씬 더 많이 들어가 있었다.
밥 위에 꼬막이 올라가 있을 것이라고 예상했지만,
예상과 달리 바닥부터 꼬막이 채워져 있었다.


꼬막비빔밥의 반을 접시에 떴다.
자세히 살펴보면 꼬막이 바닥부터 쌓여있다.


제품의 정확히 반을 접시에 덜어서 데웠다.
밥 위에 꼬막을 올렸더니 밥이 모두 덮힐 정도로 꼬막의 양이 많다.


꼬막과 쌀밥 외에도 오이고추, 김, 통깨 등이 포함되어 있다.


한 숟가락 떠서 먹어보면 꼬막비빔밥 소스의 깊은 풍미를 느낄 수 있다.


단맛 : 제법 강하다.
짠맛 : 보통이다.
매운맛 : 약하다.
감칠맛 : 강하다.


단맛, 짠맛, 매운맛, 감칠맛이 동시에 느껴진다.
제법 강한 단맛이 느껴지고, 매운맛은 약하다.
개인적으로 매운맛이 조금 더 강했으면 좋겠다는 생각이 든다.

세꼬막의 식감은 쫄깃했다.
쫄깃쫄깃하게 씹는 재미가 있었다.
누구나 좋아할 맛이다.
["나는 꼬막비빔밥에 진심이다. :smile: \n순천에서 먹었던 꼬막비빔밥은 인상적인 기억으로 남아 있다. \n와이프님께서 코스토코엘 다녀왔다. \n오늘 저녁은 꼬막비빔밥이라고 했다. \n꼬막비빔밥이라면 언제나 OK다!\n\n\n 구입처 : 코스트코\n 구입일 : 2022년 11월 23일\n 가격 : 14,990원\n\n\n코스트코에서 14,990원에 구입했다. \n꼬막이 아주 실하게 들어있다. \n참기름의 고소한 향과 꼬막의 쫄깃한 식감이 잘 어울린다.\n\n원재료\n\n 꼬막 : 38.24%\n 정제수\n 쌀 : 18.54%\n 꼬막비빔밥용소스 : 9.27%\n 참기름\n 오이고추\n 김\n 볶음참깨\n\n\n고소한 참기름 냄새\n\n냉장고를 열어보니 반가운 꼬막 비빔밥이 있었다. \n뚜껑을 열어보니 고소한 참기름 냄새가 느껴졌다.\n\n\n가장자리 부분은 쌀밥이 있었고, 가운데 부분은 꼬막이 있었다. \n꼬막은 생각보다 훨씬 더 많이 들어가 있었다. \n밥 위에 꼬막이 올라가 있을 것이라고 예상했지만, \n예상과 달리 바닥부터 꼬막이 채워져 있었다.\n\n\n꼬막비빔밥의 반을 접시에 떴다. \n자세히 살펴보면 꼬막이 바닥부터 쌓여있다.\n\n\n제품의 정확히 반을 접시에 덜어서 데웠다. \n밥 위에 꼬막을 올렸더니 밥이 모두 덮힐 정도로 꼬막의 양이 많다.\n\n\n꼬막과 쌀밥 외에도 오이고추, 김, 통깨 등이 포함되어 있다.\n\n\n한 숟가락 떠서 먹어보면 꼬막비빔밥 소스의 깊은 풍미를 느낄 수 있다.\n\n\n 단맛 : 제법 강하다.\n 짠맛 : 보통이다.\n 매운맛 : 약하다.\n 감칠맛 : 강하다.\n\n\n단맛, 짠맛, 매운맛, 감칠맛이 동시에 느껴진다. \n제법 강한 단맛이 느껴지고, 매운맛은 약하다. \n개인적으로 매운맛이 조금 더 강했으면 좋겠다는 생각이 든다.\n\n세꼬막의 식감은 쫄깃했다. \n쫄깃쫄깃하게 씹는 재미가 있었다. \n누구나 좋아할 맛이다.\n"]
Title : 우분투 리눅스에서 sudo 명령시에 루트 비밀번호 입력을 스킵하는 방법
URL : /ubuntu/2022/11/21/how-to-skip-root-password-during-sudo-command.html
Description : How to skip root password during sudo command
Content : 우분투 리눅스를 이용하여 스크립트를 작성하다보면 루트 권한이 필요한 경우가 종종 있다.
사용자가 로컬에서 직접 실행하는 스크립트라면 귀찮더라도 root 비밀번호를 입력해주면 된다.
하지만 crontab이나 서비스로 돌고 있는 스크립트에서는 admin 비밀번호를 입력할 수 없다.
이 때 특정 사용자는 sudo 명령시에 비밀번호를 입력하지 않도록 설정할 수 있다.

물론 비밀번호 없이 sudo 명령을 수행할 수 있는 것은 위험하다.
그렇기 때문에 아래 방법은 불가피할 경우에만 제한적으로 사용하기를 권장한다.

sudo 비밀번호 없이 실행할 수 있도록 설정하는 방법
visudo 명령을 통해서 권한을 설정할 수 있다.
이 부분에 대해서는 잘 알고 계실 것이라고 생각하고 바로 설명하겠다.

sudo visudo


위의 명령을 통해서 관리자 권한을 편집한다.

# User privilege specification
root ALL=(ALL:ALL) ALL
jenkins ALL=(ALL:ALL) ALL


보통은 위와 같이 jenkins ALL=(ALL:ALL) ALL로 되어 있다.
이 부분을 jenkins ALL=(ALL) NOPASSWORD:ALL로 수정하면 된다.

그 이후부터는 sudo 명령을 붙여도 비밀번호를 물어보지 않는다.

["우분투 리눅스를 이용하여 스크립트를 작성하다보면 루트 권한이 필요한 경우가 종종 있다. \n사용자가 로컬에서 직접 실행하는 스크립트라면 귀찮더라도 root 비밀번호를 입력해주면 된다. \n하지만 crontab이나 서비스로 돌고 있는 스크립트에서는 admin 비밀번호를 입력할 수 없다. \n이 때 특정 사용자는 sudo 명령시에 비밀번호를 입력하지 않도록 설정할 수 있다.\n\n물론 비밀번호 없이 sudo 명령을 수행할 수 있는 것은 위험하다. \n그렇기 때문에 아래 방법은 불가피할 경우에만 제한적으로 사용하기를 권장한다.\n\nsudo 비밀번호 없이 실행할 수 있도록 설정하는 방법\nvisudo 명령을 통해서 권한을 설정할 수 있다. \n이 부분에 대해서는 잘 알고 계실 것이라고 생각하고 바로 설명하겠다.\n\nsudo visudo\n\n\n위의 명령을 통해서 관리자 권한을 편집한다.\n\n# User privilege specification\nroot ALL=(ALL:ALL) ALL\njenkins ALL=(ALL:ALL) ALL\n\n\n보통은 위와 같이 jenkins ALL=(ALL:ALL) ALL로 되어 있다. \n이 부분을 jenkins ALL=(ALL) NOPASSWORD:ALL로 수정하면 된다.\n\n그 이후부터는 sudo 명령을 붙여도 비밀번호를 물어보지 않는다.\n\n"]
Title : 망망대해를 닻 없이 표류하는 느낌이 든다. 슬럼프가 왔다.
URL : /diary/2022/11/21/diary.html
Description : 2022년 11월 21일 일기
Content : 요즘 망망대해를 표류하는 느낌이 든다.
회사일도 재미가 없고, 블로그 수익도 미미하다.

가천 막걸리를 나눠 먹었다.


부모님께서 어제 올라오시면서 막걸리 반 말을 사오셨다.
소분해서 아파트 단지 이웃들과 나눠 먹었다.
어제 나눠줬던 막걸리 한 통을 거의 다 마셨다길래, 오늘 또 한 통을 가져다 드렸다.
오늘 보내드린 것도 거의 다 마시고 인증샷을 보내왔다.
직접 촬영한 사진은 하나도 없어서 일기에 올릴 사진은 이 뿐이다.
["요즘 망망대해를 표류하는 느낌이 든다. \n회사일도 재미가 없고, 블로그 수익도 미미하다.\n\n가천 막걸리를 나눠 먹었다.\n\n\n부모님께서 어제 올라오시면서 막걸리 반 말을 사오셨다. \n소분해서 아파트 단지 이웃들과 나눠 먹었다. \n어제 나눠줬던 막걸리 한 통을 거의 다 마셨다길래, 오늘 또 한 통을 가져다 드렸다. \n오늘 보내드린 것도 거의 다 마시고 인증샷을 보내왔다. \n직접 촬영한 사진은 하나도 없어서 일기에 올릴 사진은 이 뿐이다.\n"]
Title : SPAC 테스트 44점, 산닭오리불놀이, 성주 가천막걸리
URL : /diary/2022/11/20/diary.html
Description : 2022년 11월 20일 일기
Content : 시골집에서 부모님이 올라오셨다.
부탁했던 성주 가천막걸리도 가져오셨다.

SPAC 테스트

이럴수가! SPAC 점수가 오히려 떨어졌다.
이전 성적은 IH였는데 이번 성적은 IM이다.
나름 열심히 공부했다고 생각했는데 등급이 오히려 떨어지니 허무한 마음이 든다.
회사에 계속 남기로 결심했기 때문에 영어는 더욱 중요해졌다.
분발하자.

가천막걸리

부모님께 가천막걸리 반 말을 부탁드렸었다.
오늘 말통으로 막걸리를 받았다.
2리터 들이의 페트병에 나눠담아서 이웃분들이랑 나눠먹었다.


아윤이네
연우네
옆집


산닭오리불놀이
부모님을 모시로 의왕에 있는 산닭오리불놀이라는 맛집에 다녀왔다.
두 아들들이 모두 잘 먹어서 흐뭇했다.
자세한 방문기는 아래 티스토리 블로그 참고!






의왕 청계동 오리백숙 맛집 <산닭오리불놀이> 가족 모임으로 좋았다.
"처댁 식구들로부터 알게 된 맛집을 부모님께도 설파했다." 요즘 망망대해에 닻도 없이 표류하는 느낌이 든다. 회사일도 손에 잘 안 잡히고 운동도 귀찮다. 블로그 수익도 급감해서 글을 작성하는 것도 영 재미가 없다. 힘내서 블로그를 쓰겠다고 PC 앞에 앉았는데 딴짓만 1시간 정도 했다. 내가 쓰는 글들이 돈은 안 되더라도 추억을 기록한다는 마음으로 힘내서 써보자. 으랏차차! 마음의 힘을 옮겨 발업하고 텐션업하고 신나게 휘갈겨보자. 맛있게 먹고 마신 곳이니까 즐거운 마음으로 써보자. 오늘 기록할 맛집은 라는 곳으로, 처댁 식구들이랑 지난여름에 다녀왔던 곳이다. 두 아들이 오리백숙을 맛있게 잘 먹어서 와이프님이 홀딱 반한 곳이다. 첫째 아들은 6살이고, 둘째 아들은 2살인데 맛있는 음식과 그렇지 못한 음식은 ..








["시골집에서 부모님이 올라오셨다. \n부탁했던 성주 가천막걸리도 가져오셨다.\n\nSPAC 테스트\n\n이럴수가! SPAC 점수가 오히려 떨어졌다. \n이전 성적은 IH였는데 이번 성적은 IM이다. \n나름 열심히 공부했다고 생각했는데 등급이 오히려 떨어지니 허무한 마음이 든다. \n회사에 계속 남기로 결심했기 때문에 영어는 더욱 중요해졌다. \n분발하자.\n\n가천막걸리\n\n부모님께 가천막걸리 반 말을 부탁드렸었다. \n오늘 말통으로 막걸리를 받았다. \n2리터 들이의 페트병에 나눠담아서 이웃분들이랑 나눠먹었다.\n\n\n 아윤이네\n 연우네\n 옆집\n\n\n산닭오리불놀이\n부모님을 모시로 의왕에 있는 산닭오리불놀이라는 맛집에 다녀왔다.\n두 아들들이 모두 잘 먹어서 흐뭇했다. \n자세한 방문기는 아래 티스토리 블로그 참고!\n\n\n\n\n \n \n 의왕 청계동 오리백숙 맛집 <산닭오리불놀이> 가족 모임으로 좋았다.\n "처댁 식구들로부터 알게 된 맛집을 부모님께도 설파했다." 요즘 망망대해에 닻도 없이 표류하는 느낌이 든다. 회사일도 손에 잘 안 잡히고 운동도 귀찮다. 블로그 수익도 급감해서 글을 작성하는 것도 영 재미가 없다. 힘내서 블로그를 쓰겠다고 PC 앞에 앉았는데 딴짓만 1시간 정도 했다. 내가 쓰는 글들이 돈은 안 되더라도 추억을 기록한다는 마음으로 힘내서 써보자. 으랏차차! 마음의 힘을 옮겨 발업하고 텐션업하고 신나게 휘갈겨보자. 맛있게 먹고 마신 곳이니까 즐거운 마음으로 써보자. 오늘 기록할 맛집은 라는 곳으로, 처댁 식구들이랑 지난여름에 다녀왔던 곳이다. 두 아들이 오리백숙을 맛있게 잘 먹어서 와이프님이 홀딱 반한 곳이다. 첫째 아들은 6살이고, 둘째 아들은 2살인데 맛있는 음식과 그렇지 못한 음식은 ..\n \n \n \n \n \n \n\n\n"]
Title : 비상근 예비군 훈련
URL : /diary/2022/11/19/diary.html
Description : 2022년 11월 19일 일기 (토요일)
Content : 비상근 예비군 훈련


한 달에 한 번 정도 비상근 예비군 훈련을 다녀온다.
약 한 달만에 훈련을 다녀왔다.
이번 훈련은 특별히 체육행사로 구성되어 있었다.
족구, 야구 비슷한 운동을 했다.
현역들과 섞여서 운동을 하다보니 좀 더 끈끈해진 느낌이다.
간식으로는 맘스터치 햄버거도 먹었다.
PX에서 과자를 많이 사왔다.
["비상근 예비군 훈련\n\n\n한 달에 한 번 정도 비상근 예비군 훈련을 다녀온다. \n약 한 달만에 훈련을 다녀왔다.\n이번 훈련은 특별히 체육행사로 구성되어 있었다. \n족구, 야구 비슷한 운동을 했다. \n현역들과 섞여서 운동을 하다보니 좀 더 끈끈해진 느낌이다. \n간식으로는 맘스터치 햄버거도 먹었다. \nPX에서 과자를 많이 사왔다.\n"]
Title : 파이썬 urllib.request시에 utf-8 code can't decode byte 에러 조치 방법
URL : /python/2022/11/17/python-utf-8-code-cant-decode-byte-on-urllib-request.html
Description : Python에서 한글 인코딩 문제 해결 방법
Content : 한글을 표시하는 방법은 여러가지가 있다.
다양한 한글 코드가 존재하고, 인코딩 된 방식에 맞게 디코딩해야 한다.
파일이나 URL로부터 읽은 데이터를 처리할 때 제대로 디코딩하지 못하면 텍스트가 깨지거나 예상하지 않은 오류가 발생한다.
파이썬에서 한글 디코딩 문제가 발생할 때 해결할 수 있는 방법을 설명한다.

디코딩 문제
아래의 파이썬 스크립에서 디코딩 에러가 발생했다.

import urllib.request
try:
url = "https://boyinblue.github.io"
req = urllib.request.Request(url)
response = urllib.request.urlopen(url)
print(response.read().decode('utf-8'))
except:
print("Faild!")


위의 스크립트는 대부분의 웹페이지에서 문제 없이 동작했지만 특정 웹페이지에서는 에러가 발생했다.


utf-8 can’t decode byte


문제의 해결
자주 사용하는 한글 코드를 리스트에 넣어놓고 시도하면 된다.

import urllib.request
try:
url = "https://boyinblue.github.io"
req = urllib.request.Request(url)
response = urllib.request.urlopen(url)
data = response.read()
encodes = [ "utf-8", "euc-kr", "KSC5601", "cp949" ]
for enc in encodes:
try:
print(data.decode(enc))
except:
print("Failed by {}".format(enc))
except:
print("Faild!")


위의 스크립트는 ‘utf-8’, ‘euc-kr’, ‘KSC5601’, ‘cp949’ 4가지 코드로 디코딩을 시도한다.
현재까지 위의 방법으로 디코딩하지 못한 한글 문서나 웹페이지는 없었다.
["한글을 표시하는 방법은 여러가지가 있다. \n다양한 한글 코드가 존재하고, 인코딩 된 방식에 맞게 디코딩해야 한다. \n파일이나 URL로부터 읽은 데이터를 처리할 때 제대로 디코딩하지 못하면 텍스트가 깨지거나 예상하지 않은 오류가 발생한다. \n파이썬에서 한글 디코딩 문제가 발생할 때 해결할 수 있는 방법을 설명한다.\n\n디코딩 문제\n아래의 파이썬 스크립에서 디코딩 에러가 발생했다.\n\nimport urllib.request\ntry:\n url = \"https://boyinblue.github.io\"\n req = urllib.request.Request(url)\n response = urllib.request.urlopen(url)\n print(response.read().decode('utf-8'))\nexcept:\n print(\"Faild!\")\n\n\n위의 스크립트는 대부분의 웹페이지에서 문제 없이 동작했지만 특정 웹페이지에서는 에러가 발생했다.\n\n\n utf-8 can’t decode byte\n\n\n문제의 해결\n자주 사용하는 한글 코드를 리스트에 넣어놓고 시도하면 된다.\n\nimport urllib.request\ntry:\n url = \"https://boyinblue.github.io\"\n req = urllib.request.Request(url)\n response = urllib.request.urlopen(url)\n data = response.read()\n encodes = [ \"utf-8\", \"euc-kr\", \"KSC5601\", \"cp949\" ]\n for enc in encodes:\n try:\n print(data.decode(enc))\n except:\n print(\"Failed by {}\".format(enc))\nexcept:\n print(\"Faild!\")\n\n\n위의 스크립트는 ‘utf-8’, ‘euc-kr’, ‘KSC5601’, ‘cp949’ 4가지 코드로 디코딩을 시도한다. \n현재까지 위의 방법으로 디코딩하지 못한 한글 문서나 웹페이지는 없었다.\n"]
Title : 유모바일 알뜰요금제 기본 데이터 제공량 소진 완료시 테더링 사용 불가
URL : /memo/2022/11/17/umobile-tethering-lock.html
Description : LG 유플러스에서 LG유모바일로 통신사를 변경했다. 기본 데이터를 모두 소진하면 테더링이 불가하다.
Content : 유플러스 통신사를 오랫동안 이용했다.
최근에 약정이 종료되어서 알뜰 요금제로 변경했다.
음성 통화 및 문자 전송이 무제한이고,
데이터 통화도 1GB가 기본적으로 제공이 된다.
1GB를 모두 소진하면 1Mbps의 속도로 데이터를 무제한으로 사용할 수 있다.
요금은 한 달에 9,900원으로 아주 저렴하다.

유모바일 알뜰요금제는 모든 것이 만족스러웠다.
한가지 불편한 점이 있다면, 기본 데이터를 모두 소진하면 테더링이 안 된다는 것이다.
이 부분에 대해서 이메일로 상담을 했다.

상담사 확인사살
스마트폰 개통때도 느꼈지만 유모바일 상담은 굉장히 느리다.
셀프 개통이 제대로 되지 않아서 상담사와 통화 신청을 하고도 5일이 걸려서야 상담사와 통화를 할 수 있었다.
이메일을 통한 상담 역시도 시간이 많이 걸렸다.
간단한 답변을 듣는데 꼬박 7일이나 걸렸다.
아래는 이메일 상담 결과다.



역시나 기본 데이터가 모두 소진된 상태에서는 테더링을 이용할 수 없다는 것을 확인했다.
사무실에서 라즈베리파이에 스마트폰 테더링을 연결해서 딴짓을 많이 했는데, 이제 대놓고 스마트폰으로 딴짓을 해야 한다. :smile:

유모바일 상담은 느리다.




날짜
구분
내용


2022-10-31
개통 상담
통화 불가, 상담 예약


2022-11-4
개통 상담 및 개통
5일차


2022-11-11
테더링 관련 이메일 상담
 


2022-11-17
이메일 답변
7일차, 근무일 기준 5일차




그래도 싼 맛에 쓴다.

결론

유모바일 상담은 굉장히 힘들다.
기본 데이터 소진하면 테더링이 불가하다.

["유플러스 통신사를 오랫동안 이용했다. \n최근에 약정이 종료되어서 알뜰 요금제로 변경했다. \n음성 통화 및 문자 전송이 무제한이고, \n데이터 통화도 1GB가 기본적으로 제공이 된다. \n1GB를 모두 소진하면 1Mbps의 속도로 데이터를 무제한으로 사용할 수 있다. \n요금은 한 달에 9,900원으로 아주 저렴하다.\n\n유모바일 알뜰요금제는 모든 것이 만족스러웠다. \n한가지 불편한 점이 있다면, 기본 데이터를 모두 소진하면 테더링이 안 된다는 것이다. \n이 부분에 대해서 이메일로 상담을 했다.\n\n상담사 확인사살\n스마트폰 개통때도 느꼈지만 유모바일 상담은 굉장히 느리다. \n셀프 개통이 제대로 되지 않아서 상담사와 통화 신청을 하고도 5일이 걸려서야 상담사와 통화를 할 수 있었다. \n이메일을 통한 상담 역시도 시간이 많이 걸렸다. \n간단한 답변을 듣는데 꼬박 7일이나 걸렸다. \n아래는 이메일 상담 결과다.\n\n\n\n역시나 기본 데이터가 모두 소진된 상태에서는 테더링을 이용할 수 없다는 것을 확인했다. \n사무실에서 라즈베리파이에 스마트폰 테더링을 연결해서 딴짓을 많이 했는데, 이제 대놓고 스마트폰으로 딴짓을 해야 한다. :smile:\n\n유모바일 상담은 느리다.\n\n\n \n \n 날짜\n 구분\n 내용\n \n \n 2022-10-31\n 개통 상담\n 통화 불가, 상담 예약\n \n \n 2022-11-4\n 개통 상담 및 개통\n 5일차\n \n \n 2022-11-11\n 테더링 관련 이메일 상담\n  \n \n \n 2022-11-17\n 이메일 답변\n 7일차, 근무일 기준 5일차\n \n \n\n\n그래도 싼 맛에 쓴다.\n\n결론\n\n 유모바일 상담은 굉장히 힘들다.\n 기본 데이터 소진하면 테더링이 불가하다.\n\n"]
Title : 온라인 여권 신청 완료 (비용 51,300원)
URL : /diary/2022/11/17/%EC%98%A8%EB%9D%BC%EC%9D%B8-%EC%97%AC%EA%B6%8C-%EC%8B%A0%EC%B2%AD.html
Description : 2022년 11월 17일 (목요일) 일기
Content : 요약

✅ 온라인으로 여권을 신청했다.
✅ 메가커피 성남고등점에서 한 잔


온라인 여권 신청
화요일에 분당 미스터 포토에서 여권용 사진을 촬영했다.
촬영한 사진을 메일로 받아서 오늘 정부24에서 온라인으로 여권을 신청했다.
온라인으로 여권을 신청하는 방법은 생각외로 간단했다.
아래 절차대로 했더니 금방 큰 어려움없이 신청할 수 있었다.

여권 재발급 방법

정부24에 접속해서 로그인을 했다.
여권 신청 메뉴로 들어가서 정보를 입력했다.
사진을 업로드했다.
수수료 51,300원을 결제했다.


여권 재발급 비용
여권 재발급 비용은 5만원이다.
하지만 수수료가 1,300원 ~ 2,000원 정도 붙었다.
신용카드나 계좌이체로 결제하면 수수료가 2천원 들었다.
반면, 페이코는 1,300원으로 700원 저렴해서 페이코로 결제했다.

왜 페이코로 결제하면 카드로 결제하는 것보다 수수료가 더 저렴한지 모르겠다.

메가커피 성남고등점에서 한 잔

식사 이력




구분
메뉴
비고




아침
김치찌개
 


점심
사누끼 우동
회사 점심밥


저녁
 
 




["요약\n\n ✅ 온라인으로 여권을 신청했다.\n ✅ 메가커피 성남고등점에서 한 잔\n\n\n온라인 여권 신청\n화요일에 분당 미스터 포토에서 여권용 사진을 촬영했다. \n촬영한 사진을 메일로 받아서 오늘 정부24에서 온라인으로 여권을 신청했다. \n온라인으로 여권을 신청하는 방법은 생각외로 간단했다. \n아래 절차대로 했더니 금방 큰 어려움없이 신청할 수 있었다.\n\n여권 재발급 방법\n\n 정부24에 접속해서 로그인을 했다.\n 여권 신청 메뉴로 들어가서 정보를 입력했다.\n 사진을 업로드했다.\n 수수료 51,300원을 결제했다.\n\n\n여권 재발급 비용\n여권 재발급 비용은 5만원이다. \n하지만 수수료가 1,300원 ~ 2,000원 정도 붙었다. \n신용카드나 계좌이체로 결제하면 수수료가 2천원 들었다. \n반면, 페이코는 1,300원으로 700원 저렴해서 페이코로 결제했다.\n\n왜 페이코로 결제하면 카드로 결제하는 것보다 수수료가 더 저렴한지 모르겠다.\n\n메가커피 성남고등점에서 한 잔\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 김치찌개\n  \n \n \n 점심\n 사누끼 우동\n 회사 점심밥\n \n \n 저녁\n  \n  \n \n \n\n\n"]
Title : 삼성 Dex 배경화면을 단색으로 바꾸는 방
URL : /dex/2022/11/17/How-To-Change-Dex-Background-As-Black-Screen.html
Description : How to change background as black color on Samsung DeX Desktop
Content : 그동안 사무실에서 딴짓을 많이 했다.
라즈베리파이에 스마트폰 테더링을 연결해서 웹서핑도하고 블로그도 작성했다.
최근에 스마트폰을 알뜰요금제로 변경했다.
기본 데이터 제공량인 1GB를 모두 소진하더라도 1Mbps 속도로 데이터를 무제한 쓸 수 있다.
단, 속도가 제한된 상태에서는 테더링이 불가능하다.
이 때문에 라즈베리파이 대신에 스마트폰에 모니터와 키보드와 마우스를 연결해서 딴짓을 하기로 했다.

너무 갤럭시스러운 바탕화면

C-Type 멀티허브를 이용해서 스마트폰에 모니터와 키보드와 마우스를 연결했더니 제법 쓸만했다.
반응 속도도 제법 빠르다. 웹서핑과 블로그 작성에는 손색이 없는 속도다.
하지만 바탕화면이 문제다.
기본으로 제공되는 바탕화면 이미지는 너무 갤럭시스러워서 스마트폰을 연결해서 딴짓을 한다는 것이 쉽게 들통날 것 같았다.
그래서 바탕화면을 단색으로 변경하기로 했다.

DeX에서 단색 설정이 불가하다?
설정을 찾아봤지만 바탕화면을 단색으로 변경할 수 있는 기능은 없었다.
그래서 어쩔 수 없이 단색 이미지를 만들고 그것을 배경 이미지로 사용하기로 했다.
DeX에서 배경 이미지는 아래 2가지가 전부이다.

갤럭시에서 기본으로 제공하는 이미지 사용
사진 파일을 배경으로 사용


일단 단색 이미지를 만들자!


우선 올블랙 단색 이미지를 만들어서 그 이미지를 배경화면으로 지정하면 된다.
만들기 귀찮으면 위의 이미지를 다운로드해도 된다.

단색 이미지를 배경화면으로 등록!
단색으로 만든 이미지 파일을 배경화면으로 등록하는 방법이다.

바탕화면에서 마우스 오른쪽 버튼을 눌러 배경화면 메뉴 선택

우선 바탕화면에서 마우스 오른쪽 버튼을 눌러 배경화면 메뉴를 선택한다.

내 배경화면과 갤러리 중에서 갤러리 선택

갤러리를 선택한다.

단색 이미지 선택

미리 준비한 단색 이미지 파일을 선택한다.

홈 화면 및 잠금화면으로 설정

홈 화면 및 잠금화면으로 설정하면 된다.
물론 홈 화면으로만 설정하거나 잠금 화면으로만 설정할 수도 있다.

단색 이미지 사용해보니?
기존 바탕화면은 누가 봐도 스마트폰 바탕화면처럼 보였다.
하지만 단색 이미지로 바꿨더니 그냥 윈도우즈가 아닌 리눅스 PC처럼 보였다.
직장 동료들이나 상사들이 내 화면을 보더라도 PC로 열심히 일하는 것처럼 보일 것이다.

["그동안 사무실에서 딴짓을 많이 했다. \n라즈베리파이에 스마트폰 테더링을 연결해서 웹서핑도하고 블로그도 작성했다. \n최근에 스마트폰을 알뜰요금제로 변경했다. \n기본 데이터 제공량인 1GB를 모두 소진하더라도 1Mbps 속도로 데이터를 무제한 쓸 수 있다. \n단, 속도가 제한된 상태에서는 테더링이 불가능하다. \n이 때문에 라즈베리파이 대신에 스마트폰에 모니터와 키보드와 마우스를 연결해서 딴짓을 하기로 했다.\n\n너무 갤럭시스러운 바탕화면\n\nC-Type 멀티허브를 이용해서 스마트폰에 모니터와 키보드와 마우스를 연결했더니 제법 쓸만했다. \n반응 속도도 제법 빠르다. 웹서핑과 블로그 작성에는 손색이 없는 속도다. \n하지만 바탕화면이 문제다. \n기본으로 제공되는 바탕화면 이미지는 너무 갤럭시스러워서 스마트폰을 연결해서 딴짓을 한다는 것이 쉽게 들통날 것 같았다. \n그래서 바탕화면을 단색으로 변경하기로 했다.\n\nDeX에서 단색 설정이 불가하다?\n설정을 찾아봤지만 바탕화면을 단색으로 변경할 수 있는 기능은 없었다. \n그래서 어쩔 수 없이 단색 이미지를 만들고 그것을 배경 이미지로 사용하기로 했다. \nDeX에서 배경 이미지는 아래 2가지가 전부이다.\n\n 갤럭시에서 기본으로 제공하는 이미지 사용\n 사진 파일을 배경으로 사용\n\n\n일단 단색 이미지를 만들자!\n\n\n우선 올블랙 단색 이미지를 만들어서 그 이미지를 배경화면으로 지정하면 된다. \n만들기 귀찮으면 위의 이미지를 다운로드해도 된다.\n\n단색 이미지를 배경화면으로 등록!\n단색으로 만든 이미지 파일을 배경화면으로 등록하는 방법이다.\n\n바탕화면에서 마우스 오른쪽 버튼을 눌러 배경화면 메뉴 선택\n\n우선 바탕화면에서 마우스 오른쪽 버튼을 눌러 배경화면 메뉴를 선택한다.\n\n내 배경화면과 갤러리 중에서 갤러리 선택\n\n갤러리를 선택한다.\n\n단색 이미지 선택\n\n미리 준비한 단색 이미지 파일을 선택한다.\n\n홈 화면 및 잠금화면으로 설정\n\n홈 화면 및 잠금화면으로 설정하면 된다. \n물론 홈 화면으로만 설정하거나 잠금 화면으로만 설정할 수도 있다.\n\n단색 이미지 사용해보니?\n기존 바탕화면은 누가 봐도 스마트폰 바탕화면처럼 보였다. \n하지만 단색 이미지로 바꿨더니 그냥 윈도우즈가 아닌 리눅스 PC처럼 보였다. \n직장 동료들이나 상사들이 내 화면을 보더라도 PC로 열심히 일하는 것처럼 보일 것이다.\n\n"]
Title : 윈도우에서 파이썬 스크립트를 실행시에 python이라고만 출력되는 문제
URL : /python/2022/11/16/python-can-not-run-python-script.html
Description : Windows에서 python script가 실행되지 않는 문제 해결 방법
Content : 윈도우즈에서 파이썬 스크립트를 실행시키기 위해서 파워쉘에서 python 명령을 수행했다.
하지만 python이라는 에러 메시지만 토해내면서 실제로 수행되지 않는 문제가 발생했다.
python -h와 같은 명령에서 여전히 python이라는 메시지가 출력될 뿐이었다.

문제의 상황

리눅스에서 작성한 파이썬 스크립트를 윈도우즈로 가져와서 실행을 해봤다.

python foo.py


어이없게도 python이라는 메시지가 출력되면서 아무런 동작도 되지 않았다.

>python foo.py
python
>


python -h 명령도 실행해보았다.
-h 옵션을 붙이면 도움말을 확인할 수 있다.

>python -h


역시나 python이라는 메시지만 나오고 도움말 따위는 나오지 않았다.

문제의 원인 및 해결

문제의 원인은 파이썬이 설치되어 있지 않아서였다.

>python


위와 같이 입력했더니 비로소 Microsoft Store가 뜨면서 파이썬 패키지를 설치할 수 있었다.
파이썬이 설치되지 않았으면 차라리 파이썬 프로그램을 찾을 수 없다고 나오는게 좋겠다.
왜 파이썬이 설치되어있지 않은 상태에서 python이라는 메시지를 토해냈는지 아직도 이해할 수 없다.

결론

만약 윈도우즈에서 파이썬 스크립트가 실행되지 않는다면
파이썬이 실행되어 있는지 다시 한번 확인해보자.

["윈도우즈에서 파이썬 스크립트를 실행시키기 위해서 파워쉘에서 python 명령을 수행했다. \n하지만 python이라는 에러 메시지만 토해내면서 실제로 수행되지 않는 문제가 발생했다. \npython -h와 같은 명령에서 여전히 python이라는 메시지가 출력될 뿐이었다.\n\n문제의 상황\n\n리눅스에서 작성한 파이썬 스크립트를 윈도우즈로 가져와서 실행을 해봤다.\n\npython foo.py\n\n\n어이없게도 python이라는 메시지가 출력되면서 아무런 동작도 되지 않았다.\n\n>python foo.py\npython\n>\n\n\npython -h 명령도 실행해보았다.\n-h 옵션을 붙이면 도움말을 확인할 수 있다.\n\n>python -h\n\n\n역시나 python이라는 메시지만 나오고 도움말 따위는 나오지 않았다.\n\n문제의 원인 및 해결\n\n문제의 원인은 파이썬이 설치되어 있지 않아서였다.\n\n>python\n\n\n위와 같이 입력했더니 비로소 Microsoft Store가 뜨면서 파이썬 패키지를 설치할 수 있었다. \n파이썬이 설치되지 않았으면 차라리 파이썬 프로그램을 찾을 수 없다고 나오는게 좋겠다. \n왜 파이썬이 설치되어있지 않은 상태에서 python이라는 메시지를 토해냈는지 아직도 이해할 수 없다.\n\n결론\n\n만약 윈도우즈에서 파이썬 스크립트가 실행되지 않는다면 \n파이썬이 실행되어 있는지 다시 한번 확인해보자.\n\n"]
Title : C언어 배열에 5개의 숫자를 입력받아 합을 출력하는 소스 코드 예제
URL : /c/2022/11/16/%EB%B0%B0%EC%97%B4-%EC%9E%85%EB%A0%A5%EB%B0%9B%EC%9D%80-%EC%88%AB%EC%9E%90%EC%9D%98-%ED%95%A9-%EC%B6%9C%EB%A0%A5.html
Description : 지식인 432811400 답변
Content : 지식인에 올라온 질문에 대한 답변을 작성한다.


질의번호 : 432811400


문제의 정의

5개의 숫자를 배열로 입력받아 합을 출력한다.

동작 정의


표준 입력으로 숫자 5개를 입력받아 배열에 저장한다.
배열에 저장된 5개의 항목을 순회하여 합을 구하여 출력한다.


문법 설명

배열의 선언

int arr[5] = {0,};


정수형 인자를 5개 가진 배열을 선언하고, 0으로 초기화한다.

표준 입력

scanf("%d", &arr[0])


표준 입력으로 정수를 입력받아 0번 배열에 저장한다.

int i = 0;
for ( ; i < 5 ; i++ )
{
scanf("%d", %arr[i]);
}


배열의 모든 항목을 순회하여 합을 구하기

int i = 0;
int sum = 0;

for ( ; i < 5 ; i++ )
{
sum += arr[i];
}


구한 합을 출력하기

printf("%d", sum);


전체 소스

#include <stdio.h>

int main()
{
int arr[5] = {0,};
int i = 0;
int sum = 0;

for ( ; i < 5 ; i++ )
{
scanf("%d", &arr[i]);
}

for ( i = 0 ; i < 5 ; i++ )
{
sum += arr[i];
}

printf("%d", sum);
}

["지식인에 올라온 질문에 대한 답변을 작성한다.\n\n\n 질의번호 : 432811400\n\n\n문제의 정의\n\n5개의 숫자를 배열로 입력받아 합을 출력한다.\n\n동작 정의\n\n\n 표준 입력으로 숫자 5개를 입력받아 배열에 저장한다.\n 배열에 저장된 5개의 항목을 순회하여 합을 구하여 출력한다.\n\n\n문법 설명\n\n배열의 선언\n\nint arr[5] = {0,};\n\n\n정수형 인자를 5개 가진 배열을 선언하고, 0으로 초기화한다.\n\n표준 입력\n\nscanf(\"%d\", &arr[0])\n\n\n표준 입력으로 정수를 입력받아 0번 배열에 저장한다.\n\nint i = 0;\nfor ( ; i < 5 ; i++ )\n{\n scanf(\"%d\", %arr[i]);\n}\n\n\n배열의 모든 항목을 순회하여 합을 구하기\n\nint i = 0;\nint sum = 0;\n\nfor ( ; i < 5 ; i++ )\n{\n sum += arr[i];\n}\n\n\n구한 합을 출력하기\n\nprintf(\"%d\", sum);\n\n\n전체 소스\n\n#include <stdio.h>\n\nint main()\n{\n int arr[5] = {0,};\n int i = 0;\n int sum = 0;\n\n for ( ; i < 5 ; i++ )\n {\n scanf(\"%d\", &arr[i]);\n }\n\n for ( i = 0 ; i < 5 ; i++ )\n {\n sum += arr[i];\n }\n\n printf(\"%d\", sum);\n}\n\n"]
Title : 배열 입력받은 숫자의 합 출력
URL : /2022/11/16/%EB%B0%B0%EC%97%B4-%EC%9E%85%EB%A0%A5%EB%B0%9B%EC%9D%80-%EC%88%AB%EC%9E%90%EC%9D%98-%ED%95%A9-%EC%B6%9C%EB%A0%A5.c
Description :
Content : #include

int main()
{
int arr[5] = {0,};
int i = 0;
int sum = 0;

for ( ; i < 5 ; i++ )
{
scanf("%d", &arr[i]);
}

for ( i = 0 ; i < 5 ; i++ )
{
sum += arr[i];
}

printf("%d", sum);
}
["#include \n\nint main()\n{\n int arr[5] = {0,};\n int i = 0;\n int sum = 0;\n\n for ( ; i < 5 ; i++ )\n {\n scanf(\"%d\", &arr[i]);\n }\n\n for ( i = 0 ; i < 5 ; i++ )\n {\n sum += arr[i];\n }\n\n printf(\"%d\", sum);\n}\n"]
Title : 여권용 사진 촬영, 홈플래닛 USB Type-C 멀티허브 리뷰
URL : /diary/2022/11/15/%EC%97%AC%EA%B6%8C%EC%9A%A9-%EC%A6%9D%EB%AA%85%EC%82%AC%EC%A7%84-%EC%B4%AC%EC%98%81-%EB%B6%84%EB%8B%B9-%EC%84%9C%ED%98%84%EC%97%AD-%EB%AF%B8%EC%8A%A4%ED%84%B0%ED%8F%AC%ED%86%A0.html
Description : 2022년 11월 15일 (화요일)
Content : 요약

✅ 정수용 수석님 모친상
✅ 홈플래닛 8포트 멀티 허브 리뷰
✅ 레이 운전석 사이드 미러 구입
✅ 여권 사진 촬영


정수용 수석님 모친상
일요일에 정수용 수석님의 모친께서 별세하셨다.
월요일이 연차라서 오늘 출근해서 확인을 했다.
내 결혼식때 축의금을 얼마나 하셨는지 확인해봤는데 안 하셨다.
곰곰 생각해보니 내가 결혼할 때 수석님께서는 퇴직 상태였던 것 같다.
조의금을 5만원 송금했다.
삼가 고인의 명복을 빕니다.

홈플래닛 8포트 멀티 허브 리뷰

라즈베리파이에 스마트폰 테더링을 이용해서 잘 사용하고 있었다.
최근에 유모바일 알뜰 요금제로 변경하면서 테더링이 제대로 되지 않았다.
어쩔 수 없이 스마트폰에 직접 모니터와 키보드와 마우스를 연결해서 사용하기로 했다.
USB C-Type 멀티허브를 구입해서 삼성Dex를 잘 활용하고 있다.
기존에 사용하던 우분투 리눅스에 비해서 불편하다.
파이썬으로 작성한 GUI 스크립트를 실행할 수 없다.
모든 프로그램을 안드로이드 앱으로 작성할 수도 없고 답답하다.






스마트폰 C Type Hub 리뷰 - HOME PLANET 8 PORT ETHERNET MULTI HUB
HDMI로 스마트폰을 PC처럼 쓸 수 있다. 아주 만족스럽다. C Type Hub를 구입하게 된 배경 사무실에서 딴짓을 많이 하는 편이다. 미니 컴퓨터인 라즈베리파이에 스마트폰 테더링을 연결해서 잘 사용해왔다. 사무실에서 딴짓을 해도 사람들이 열심히 일하는지 안다. 그러다가 스마트폰 요금제를 바꾸게 되었다. 기존 LG 유플러스는 기본 데이터를 모두 소진하더라도 1 MBps 속도로 무제한으로 인터넷을 이용할 수 있었다. 제한된 속도에서도 테더링을 문제없이 사용할 수 있었다. 하지만 최근에 알뜰요금제인 유모바일로 갈아탄 후부터 기존 데이터 제공량을 모두 소진하면 그 이후부터는 테더링이 불가능했다. 어쩔 수 없이 라즈베리파이가 아닌 스마트폰으로 딴짓을 해야 했다. 스마트폰을 PC처럼 이용하려면 모니터와 키보드..









레이 운전석 사이드미러 구입
의왕시 오전동 대명솔채아파트에 살 때 주차중인 레이가 뺑소니를 당한 적이 있다.
사이드 미러가 고장난 상태로 몇 년 동안 운행하다가 최근에는 거울이 자꾸 빠져서 테이프로 고정해서 사용하고 있었다.
와이프님께서 불편해서 운행하기 힘들다고해서 기아 부품 대리점에 주문을 넣었다.


대리점 : 현대모비스 기아부품대리점 현성
주소 : 경기도 성남시 중원구 마지로 428
전화번호 : 031-751-0789
부품 가격 : 98,560원
계좌 번호 : 1006501401216 우리은행 장동석
주문일 : 2022년 11월 15일 오후 5시
수령 가능일 : 2022년 11월 16일 오후 1시


여권 사진 촬영



촬영 장소 : 미스터포토 (성남시 분당구 서현동 268-4 서현프라자 3층)


여권이 만료된지도 2년이 지났다.
올 연말에 베트남에 다녀올 예정이다.
여권을 만들기 위해서 사진을 찍었다.
나도 찍고 둘째 아들도 찍었다.
둘째 아들 사진은 아주 수월하게 찍었다.

AK플라자 오장동흥남집 (저녁식사)

촬영한 여권 사진이 출력되는데는 약 1시간정도 소요된다고 했다.
그래서 서현역 AK플라자에서 저녁을 먹기로 했다.
회냉면과 갈비탕을 먹었다.

식사 이력




구분
메뉴
비고




아침
생략
 


점심
바지락 칼국수
회사밥


저녁
회냉면, 갈비탕
서현역 AK프라자




지출




내용
금액
장소
비고




여권 사진 촬영
 
미스터포토
 


과자 구입
4,500원
과자킹
 


씨앗호떡 구입
4,500원
서현역 앞 포장마차
 




["요약\n\n ✅ 정수용 수석님 모친상\n ✅ 홈플래닛 8포트 멀티 허브 리뷰\n ✅ 레이 운전석 사이드 미러 구입\n ✅ 여권 사진 촬영\n\n\n정수용 수석님 모친상\n일요일에 정수용 수석님의 모친께서 별세하셨다. \n월요일이 연차라서 오늘 출근해서 확인을 했다. \n내 결혼식때 축의금을 얼마나 하셨는지 확인해봤는데 안 하셨다. \n곰곰 생각해보니 내가 결혼할 때 수석님께서는 퇴직 상태였던 것 같다. \n조의금을 5만원 송금했다. \n삼가 고인의 명복을 빕니다.\n\n홈플래닛 8포트 멀티 허브 리뷰\n\n라즈베리파이에 스마트폰 테더링을 이용해서 잘 사용하고 있었다. \n최근에 유모바일 알뜰 요금제로 변경하면서 테더링이 제대로 되지 않았다. \n어쩔 수 없이 스마트폰에 직접 모니터와 키보드와 마우스를 연결해서 사용하기로 했다. \nUSB C-Type 멀티허브를 구입해서 삼성Dex를 잘 활용하고 있다. \n기존에 사용하던 우분투 리눅스에 비해서 불편하다. \n파이썬으로 작성한 GUI 스크립트를 실행할 수 없다. \n모든 프로그램을 안드로이드 앱으로 작성할 수도 없고 답답하다.\n\n\n\n\n \n \n 스마트폰 C Type Hub 리뷰 - HOME PLANET 8 PORT ETHERNET MULTI HUB\n HDMI로 스마트폰을 PC처럼 쓸 수 있다. 아주 만족스럽다. C Type Hub를 구입하게 된 배경 사무실에서 딴짓을 많이 하는 편이다. 미니 컴퓨터인 라즈베리파이에 스마트폰 테더링을 연결해서 잘 사용해왔다. 사무실에서 딴짓을 해도 사람들이 열심히 일하는지 안다. 그러다가 스마트폰 요금제를 바꾸게 되었다. 기존 LG 유플러스는 기본 데이터를 모두 소진하더라도 1 MBps 속도로 무제한으로 인터넷을 이용할 수 있었다. 제한된 속도에서도 테더링을 문제없이 사용할 수 있었다. 하지만 최근에 알뜰요금제인 유모바일로 갈아탄 후부터 기존 데이터 제공량을 모두 소진하면 그 이후부터는 테더링이 불가능했다. 어쩔 수 없이 라즈베리파이가 아닌 스마트폰으로 딴짓을 해야 했다. 스마트폰을 PC처럼 이용하려면 모니터와 키보드..\n \n \n \n \n \n \n\n\n\n레이 운전석 사이드미러 구입\n의왕시 오전동 대명솔채아파트에 살 때 주차중인 레이가 뺑소니를 당한 적이 있다. \n사이드 미러가 고장난 상태로 몇 년 동안 운행하다가 최근에는 거울이 자꾸 빠져서 테이프로 고정해서 사용하고 있었다. \n와이프님께서 불편해서 운행하기 힘들다고해서 기아 부품 대리점에 주문을 넣었다.\n\n\n 대리점 : 현대모비스 기아부품대리점 현성\n 주소 : 경기도 성남시 중원구 마지로 428\n 전화번호 : 031-751-0789\n 부품 가격 : 98,560원\n 계좌 번호 : 1006501401216 우리은행 장동석\n 주문일 : 2022년 11월 15일 오후 5시\n 수령 가능일 : 2022년 11월 16일 오후 1시\n\n\n여권 사진 촬영\n\n\n\n 촬영 장소 : 미스터포토 (성남시 분당구 서현동 268-4 서현프라자 3층)\n\n\n여권이 만료된지도 2년이 지났다. \n올 연말에 베트남에 다녀올 예정이다. \n여권을 만들기 위해서 사진을 찍었다. \n나도 찍고 둘째 아들도 찍었다. \n둘째 아들 사진은 아주 수월하게 찍었다.\n\nAK플라자 오장동흥남집 (저녁식사)\n\n촬영한 여권 사진이 출력되는데는 약 1시간정도 소요된다고 했다. \n그래서 서현역 AK플라자에서 저녁을 먹기로 했다. \n회냉면과 갈비탕을 먹었다.\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 생략\n  \n \n \n 점심\n 바지락 칼국수\n 회사밥\n \n \n 저녁\n 회냉면, 갈비탕\n 서현역 AK프라자\n \n \n\n\n지출\n\n\n \n \n 내용\n 금액\n 장소\n 비고\n \n \n \n \n 여권 사진 촬영\n  \n 미스터포토\n  \n \n \n 과자 구입\n 4,500원\n 과자킹\n  \n \n \n 씨앗호떡 구입\n 4,500원\n 서현역 앞 포장마차\n  \n \n \n\n\n"]
Title : 안드로이드에서 ssh 쉘 실행시키는 방법 (Termius 앱 사용)
URL : /dex/2022/11/15/how-to-use-ssh-on-android-smart-phone.html
Description : 갤럭시 스마트폰에서 제공하는 Dex에서 ssh 터미널을 사용하는 방법입니다.
Content : 삼성 갤럭시 S10 스마트폰을 2년 넘게 사용했다.
그동안 DeX를 한 번도 사용할 기회가 없었다.
최근 C-Type 멀티 허브를 구입해서 DeX를 사용해보니 무척 편리했다.
내 스마트폰을 PC처럼 사용할 수 있는데 이 편리한 것을 왜 사용하지 않았나 싶다.
지금도 모니터, 키보드, 마우스를 스마트폰에 연결해서 이 페이지를 작성하고 있다.

C-Type 멀티허브 연결
삼성 DeX를 편리하게 사용하기 위해서는 C-Type 멀티허브를 구입해서 연결하는게 좋다.
8포트짜리 멀티허브를 구입했는데 이더넷, HDMI, USB 3.0, C-Type, SD Card, Micro SD Card 등 포트들을 제공해서 편리했다.
멀티 허브에 삼성 스마트폰을 연결하면 아래 화면처럼 DeX 화면이 뜬다.


Termius 설치

SSH 쉘을 이용해서 작업하는 것을 좋아한다.
안드로이드 운영체제에서 SSH 쉘에 로그인할 수 있는 앱을 찾아봤다.
몇가지 SSH 앱을 설치해서 사용해봤지만 Termius(터미어스) 앱이 가장 편리하다.
앱스토어를 실행시켜서 Termius라는 프로그램을 설치하자.

Termius 쉘 실행

앱을 실행시키는 어렵지 않에 SSH 세션을 시작할 수 있다.
속도도 빠르고 디자인도 마음에 든다.

Termius 단점
Ctrl + C와 Ctrl + V 기능이 동작하지 않아서 이게 제법 불편하다.
Ctrl + Insert 와 Shift + Insert 단축키도 시도해봤지만 동작하지 않았다.
마우스 버튼을 이용해서 복사하기나 붙여넣기가 메뉴가 사용 가능한지 확인해봤으나 이 역시도 동작하지 않았다.
["삼성 갤럭시 S10 스마트폰을 2년 넘게 사용했다. \n그동안 DeX를 한 번도 사용할 기회가 없었다. \n최근 C-Type 멀티 허브를 구입해서 DeX를 사용해보니 무척 편리했다. \n내 스마트폰을 PC처럼 사용할 수 있는데 이 편리한 것을 왜 사용하지 않았나 싶다. \n지금도 모니터, 키보드, 마우스를 스마트폰에 연결해서 이 페이지를 작성하고 있다.\n\nC-Type 멀티허브 연결\n삼성 DeX를 편리하게 사용하기 위해서는 C-Type 멀티허브를 구입해서 연결하는게 좋다. \n8포트짜리 멀티허브를 구입했는데 이더넷, HDMI, USB 3.0, C-Type, SD Card, Micro SD Card 등 포트들을 제공해서 편리했다. \n멀티 허브에 삼성 스마트폰을 연결하면 아래 화면처럼 DeX 화면이 뜬다. \n\n\nTermius 설치\n\nSSH 쉘을 이용해서 작업하는 것을 좋아한다. \n안드로이드 운영체제에서 SSH 쉘에 로그인할 수 있는 앱을 찾아봤다. \n몇가지 SSH 앱을 설치해서 사용해봤지만 Termius(터미어스) 앱이 가장 편리하다. \n앱스토어를 실행시켜서 Termius라는 프로그램을 설치하자.\n\nTermius 쉘 실행\n\n앱을 실행시키는 어렵지 않에 SSH 세션을 시작할 수 있다. \n속도도 빠르고 디자인도 마음에 든다.\n\nTermius 단점\nCtrl + C와 Ctrl + V 기능이 동작하지 않아서 이게 제법 불편하다. \nCtrl + Insert 와 Shift + Insert 단축키도 시도해봤지만 동작하지 않았다. \n마우스 버튼을 이용해서 복사하기나 붙여넣기가 메뉴가 사용 가능한지 확인해봤으나 이 역시도 동작하지 않았다.\n"]
Title : Github Pages에 giscus 연동하는 방법
URL : /github-pages/2022/11/14/%EA%B9%83%ED%97%88%EB%B8%8C-%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B8%B0%EC%8A%A4%EC%BB%A4%EC%8A%A4-%EC%97%B0%EB%8F%99-%EB%B0%A9%EB%B2%95.html
Description : How to embed discussion on the GitHub pages.
Content : 네이버 블로그, 티스토리 블로그, 워드프레스 블로그 등은 기본적으로 댓글 기능을 제공한다.
하지만 GitHub Pages는 대표적인 정적 웹서버이기 때문에 동적 서비스인 댓글 기능이 불가능하다.

disqus나 giscus 같은 서비스를 연동하면 Github Pages에서도 방문자의 의견이나 질문을 확인할 수 있다.
giscus를 이용해서 댓글 기능을 연동하는 방법을 설명한다.

GitHub Pages에서 기본적으로 불가능한 기능

앞서 언급했듯이, GitHub Pages는 정적 웹호스팅 서비스이기 때문에 기본적으로 아래 기능들이 불가능하다.


댓글 기능
방문자수 카운트 기능
검색 기능


GitHub Pages 자체적으로 위의 기능들을 제공하지는 않지만 대안은 있다.
댓글 기능은 disqus나 giscus 서비스를 이용하면 되고,
방문자수 확인 기능은 hit.sh 서비스를 이용하면 된다.
검색 기능은 어떻게 해야 할지 고민중이다.

giscus 연동 방법

Github pages에 댓글 기능을 사용하기 위해서는 giscus라는 서비스를 이용하면 된다.
아래와 같은 장점이 있다.


오픈소스이기 때문에 누구나 무료로 사용할 수 있다.
Github의 discussion 기능을 사용하기 때문에 DB가 필요 없다.
한국어를 지원한다.





언어를 한국어로 설정한다.
Repository를 선택한다.
Discussion 제목이 페이지 경로를 포함을 선택한다.




카테고리를 General로 선택한다.
이 카테고리에서만 Discussion 찾기를 선택한다.
메인 포스트에 반응 남기기를 선택한다.
테마를 선택한다.



댓글을 표시할 페이지에 아래와 같은 형식의 스크립트를 추가하면 된다.
giscus 홈페이지에 자동 생성되는 스크립트를 그대로 사용하면 된다.


아래 스크립트는 예시이므로 반드신 giscus 홈페이지에서 생성되는 스크립트를 사용해야 한다. (아래 예시 스크립트 복붙 금지!)


<script src="https://giscus.app/client.js"
data-repo="boyinblue/boyinblue.github.io"
data-repo-id="R_kgDOG9CT0w"
data-category="General"
data-category-id="DIC_kwDOG9CT084CSLjU"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="bottom"
data-theme="preferred_color_scheme"
data-lang="ko"
crossorigin="anonymous"
async>
</script>


위의 스크립트를 body-giscus.html 파일로 생선한 후,
layout에서 include 해서 사용하도록 하였다.
이렇게 하면 다양한 레이아웃에서 원하는 위치에 giscus를 삽입할 수 있다.

body-giscus.html 파일 작성

<!-- start of body header (_includes/body-discus.html) -->

<aside id="disqus_window" class="aside_inner" style="display:none;">
<small style="background-color: #f4d03f; color: #000000; border-radius: 3px; padding: 3px 5px; font-size: 16px; font-weight: bold; text-decoration: none;">댓글 및 토론</small><br />
<script src="https://giscus.app/client.js"
data-repo="boyinblue/boyinblue.github.io"
data-repo-id="R_kgDOG9CT0w"
data-category="General"
data-category-id="DIC_kwDOG9CT084CSLjU"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="bottom"
data-theme="preferred_color_scheme"
data-lang="ko"
crossorigin="anonymous"
async>
</script>
</aside>

<!-- end of body header (_includes/body-giscus.html) -->


layout에서 body-giscus.html 파일을 재사용

<!-- giscus -->

{% include body-giscus.html %}



giscus 홈페이지
아래의 gitcus 홈페이지에 접속하면 누구나 큰 어려움 없이 giscus를 연동할 수 있다.






giscus
A comments widget built on GitHub Discussions.









도움이 될만한 글
Github Pages에 방문자수 표시하는 방법






GitHub Pages에 방문자수 카운터 표시하는 방법 (feat. hits.sh)
깃허브 페이지스 블로그에 방문자수 카운터 표시하는 방법









검색 기능 활성화 방법






[Jekyll] 검색(Search) 기능 만들기/ Github 블로그 검색(Search) 기능
검색(Search) 기능 만들기 [ 본 포스팅은 기본적인 블로그가 만들어져 있다고 가정하고 진행합니다. ] 블로그에 글이 점점 많아지면서 내 자신도 내 글을 찾기가 점점 힘들어지고 있다는걸 깨달았습니다. 페이징을 하나하나 넘겨가면서 내 글을 찾아서 보는것이 상당히 비효율적입니다. 제 블로그에서 정보를 찾으시는 분들도 관련 글을 찾고 싶을 수도 있다는 생각에 검색 기능을 추가 하게 되었습니다. 참고 사이트 Simple-Jekyll-Search 한량넷 Hyeyeon yakuza 소스파일 보기 search.json 만들기 root 경로(최상위 경로)에 search.json 를 만들고 소스 입력. root 경로는 github.io로 끝나는 디렉토리를 말합니다. jekyll 블로그게 만들어져 있다면 _config..








["네이버 블로그, 티스토리 블로그, 워드프레스 블로그 등은 기본적으로 댓글 기능을 제공한다. \n하지만 GitHub Pages는 대표적인 정적 웹서버이기 때문에 동적 서비스인 댓글 기능이 불가능하다.\n\ndisqus나 giscus 같은 서비스를 연동하면 Github Pages에서도 방문자의 의견이나 질문을 확인할 수 있다. \ngiscus를 이용해서 댓글 기능을 연동하는 방법을 설명한다.\n\nGitHub Pages에서 기본적으로 불가능한 기능\n\n앞서 언급했듯이, GitHub Pages는 정적 웹호스팅 서비스이기 때문에 기본적으로 아래 기능들이 불가능하다.\n\n\n 댓글 기능\n 방문자수 카운트 기능\n 검색 기능\n\n\nGitHub Pages 자체적으로 위의 기능들을 제공하지는 않지만 대안은 있다. \n댓글 기능은 disqus나 giscus 서비스를 이용하면 되고, \n방문자수 확인 기능은 hit.sh 서비스를 이용하면 된다. \n검색 기능은 어떻게 해야 할지 고민중이다.\n\ngiscus 연동 방법\n\nGithub pages에 댓글 기능을 사용하기 위해서는 giscus라는 서비스를 이용하면 된다. \n아래와 같은 장점이 있다.\n\n\n 오픈소스이기 때문에 누구나 무료로 사용할 수 있다.\n Github의 discussion 기능을 사용하기 때문에 DB가 필요 없다.\n 한국어를 지원한다.\n\n\n\n\n\n 언어를 한국어로 설정한다.\n Repository를 선택한다.\n Discussion 제목이 페이지 경로를 포함을 선택한다.\n\n\n\n\n 카테고리를 General로 선택한다.\n 이 카테고리에서만 Discussion 찾기를 선택한다.\n 메인 포스트에 반응 남기기를 선택한다.\n 테마를 선택한다.\n\n\n\n댓글을 표시할 페이지에 아래와 같은 형식의 스크립트를 추가하면 된다. \ngiscus 홈페이지에 자동 생성되는 스크립트를 그대로 사용하면 된다.\n\n\n 아래 스크립트는 예시이므로 반드신 giscus 홈페이지에서 생성되는 스크립트를 사용해야 한다. (아래 예시 스크립트 복붙 금지!)\n\n\n<script src=\"https://giscus.app/client.js\"\n data-repo=\"boyinblue/boyinblue.github.io\"\n data-repo-id=\"R_kgDOG9CT0w\"\n data-category=\"General\"\n data-category-id=\"DIC_kwDOG9CT084CSLjU\"\n data-mapping=\"pathname\"\n data-strict=\"0\"\n data-reactions-enabled=\"1\"\n data-emit-metadata=\"0\"\n data-input-position=\"bottom\"\n data-theme=\"preferred_color_scheme\"\n data-lang=\"ko\"\n crossorigin=\"anonymous\"\n async>\n</script>\n\n\n위의 스크립트를 body-giscus.html 파일로 생선한 후, \nlayout에서 include 해서 사용하도록 하였다. \n이렇게 하면 다양한 레이아웃에서 원하는 위치에 giscus를 삽입할 수 있다.\n\nbody-giscus.html 파일 작성\n\n<!-- start of body header (_includes/body-discus.html) -->\n\n <aside id=\"disqus_window\" class=\"aside_inner\" style=\"display:none;\">\n <small style=\"background-color: #f4d03f; color: #000000; border-radius: 3px; padding: 3px 5px; font-size: 16px; font-weight: bold; text-decoration: none;\">댓글 및 토론</small><br />\n <script src=\"https://giscus.app/client.js\"\n data-repo=\"boyinblue/boyinblue.github.io\"\n data-repo-id=\"R_kgDOG9CT0w\"\n data-category=\"General\"\n data-category-id=\"DIC_kwDOG9CT084CSLjU\"\n data-mapping=\"pathname\"\n data-strict=\"0\"\n data-reactions-enabled=\"1\"\n data-emit-metadata=\"0\"\n data-input-position=\"bottom\"\n data-theme=\"preferred_color_scheme\"\n data-lang=\"ko\"\n crossorigin=\"anonymous\"\n async>\n </script>\n </aside>\n\n<!-- end of body header (_includes/body-giscus.html) -->\n\n\nlayout에서 body-giscus.html 파일을 재사용\n\n <!-- giscus -->\n \n {% include body-giscus.html %}\n \n\n\ngiscus 홈페이지\n아래의 gitcus 홈페이지에 접속하면 누구나 큰 어려움 없이 giscus를 연동할 수 있다.\n\n\n\n\n \n \n giscus\n A comments widget built on GitHub Discussions.\n \n \n \n \n \n \n\n\n\n도움이 될만한 글\nGithub Pages에 방문자수 표시하는 방법\n\n\n\n\n \n \n GitHub Pages에 방문자수 카운터 표시하는 방법 (feat. hits.sh)\n 깃허브 페이지스 블로그에 방문자수 카운터 표시하는 방법\n \n \n \n \n \n \n\n\n\n검색 기능 활성화 방법\n\n\n\n\n \n \n [Jekyll] 검색(Search) 기능 만들기/ Github 블로그 검색(Search) 기능\n 검색(Search) 기능 만들기 [ 본 포스팅은 기본적인 블로그가 만들어져 있다고 가정하고 진행합니다. ] 블로그에 글이 점점 많아지면서 내 자신도 내 글을 찾기가 점점 힘들어지고 있다는걸 깨달았습니다. 페이징을 하나하나 넘겨가면서 내 글을 찾아서 보는것이 상당히 비효율적입니다. 제 블로그에서 정보를 찾으시는 분들도 관련 글을 찾고 싶을 수도 있다는 생각에 검색 기능을 추가 하게 되었습니다. 참고 사이트 Simple-Jekyll-Search 한량넷 Hyeyeon yakuza 소스파일 보기 search.json 만들기 root 경로(최상위 경로)에 search.json 를 만들고 소스 입력. root 경로는 github.io로 끝나는 디렉토리를 말합니다. jekyll 블로그게 만들어져 있다면 _config..\n \n \n \n \n \n \n\n\n"]
Title : 차병원 알레르기 검사 + 성남시 여수동 고궁 중국집 후기 + 신도림 족발신선생 후기
URL : /diary/2022/11/14/diary.html
Description : 22년 11월 14일 일기
Content : 굉장히 많은 일들이 있었던 하루다.
신나게 놀았고, 둘째 아들 채혈하는 것을 보고 마음이 아팠으며, 맛있는 것을 많이 먹었던 하루다.


✅ : 포천 여행에서 돌아옴
✅ : 둘째 알레르기 검사 (차병원 소아청소년과)
✅ : 성남시 여수동 고궁 중국집 후기
✅ : 신도림 족발신선생 후기


포천 여행에서 돌아옴

포천 토담키즈 풀빌라 108동에서 1박을 하고 돌아왔다.
장인어르신께서 암이 재발한 이후로 가족 여행을 자주 다니는 중이다.
토담키즈 풀빌라는 지난 9월 24일에 1박을 한 이후로 51일만에 다시 찾았다.




일시
투숙
비고




2022-09-24
107동
 


2022-11-13
108동
 




우리 아들이 태워주는 카트






포천 토담키즈 풀빌라 카트 무제한 무료
포천 토담키즈 풀빌라에서 1박 2일동안 투숙했다. 무료로 이용할 수 있는 카트는 아이들에게 인기 짱이다. 첫째 아들이 운전하는 카트 뒷편에서 속도감을 만끽했다.









토담키즈 풀빌라에 투숙하면 무료로 카트를 이용할 수 있다.

둘째 알레르기 검사
차병원 소아청소년과에서 둘째 아들의 아토피 진료를 봤다.
지혜미 교수님께서 정말 상세하게 진료를 해주셨다.
진료라기보다는 1:1 과외 교습을 받은 느낌이다.

알레르기 검사를 위해서 피를 굉장히 많이 뽑았다.
둘째 아들이 괴로워하는 모습을 보는데 너무 안타까웠다.






둘째 아토피 치료 관련 기록
완치를 위한 관리 방법을 메모한다.









성남시 여수동 고궁 중국집 방문


성남시 여수동 고궁 중국집을 방문했다.
이전에 전단지만 가지고 블로그를 썼던 적이 있었는데 방문하지도 않은 장소를 블로그에 기록했음에도 불구하고 많은 사람들이 내 글을 보았다.
둘째 아들 채혈하는 것을 보고 많이 힘들어서 중국집에서 외식을 하기로 했다.

신도림 족발신선생 후기


옆집 이웃님께서 퇴근하시면서 족발신선생에서 족발을 포장해주셨다.
태어나서 먹어 본 족발중에서 손에 꼽을 정도의 맛이었다.



야들야들하면서도 쫄깃쫄깃한 화덕 족발은 스모키한 냄새가 확 올라왔다.
불향을 제대로 입혔고 짜지 않아서 마음에 들었다.



족발과 궁합이 좋은 막국수는 참기름 향이 인상적이었다.

나중에 신도림에 갈 일이 있다면 꼭 다시 들리고 싶은 곳이다.
["굉장히 많은 일들이 있었던 하루다. \n신나게 놀았고, 둘째 아들 채혈하는 것을 보고 마음이 아팠으며, 맛있는 것을 많이 먹었던 하루다.\n\n\n ✅ : 포천 여행에서 돌아옴\n ✅ : 둘째 알레르기 검사 (차병원 소아청소년과)\n ✅ : 성남시 여수동 고궁 중국집 후기\n ✅ : 신도림 족발신선생 후기\n\n\n포천 여행에서 돌아옴\n\n포천 토담키즈 풀빌라 108동에서 1박을 하고 돌아왔다. \n장인어르신께서 암이 재발한 이후로 가족 여행을 자주 다니는 중이다. \n토담키즈 풀빌라는 지난 9월 24일에 1박을 한 이후로 51일만에 다시 찾았다.\n\n\n \n \n 일시\n 투숙\n 비고\n \n \n \n \n 2022-09-24\n 107동\n  \n \n \n 2022-11-13\n 108동\n  \n \n \n\n\n우리 아들이 태워주는 카트\n\n\n\n\n \n \n 포천 토담키즈 풀빌라 카트 무제한 무료\n 포천 토담키즈 풀빌라에서 1박 2일동안 투숙했다. 무료로 이용할 수 있는 카트는 아이들에게 인기 짱이다. 첫째 아들이 운전하는 카트 뒷편에서 속도감을 만끽했다.\n \n \n \n \n \n \n\n\n\n토담키즈 풀빌라에 투숙하면 무료로 카트를 이용할 수 있다.\n\n둘째 알레르기 검사\n차병원 소아청소년과에서 둘째 아들의 아토피 진료를 봤다. \n지혜미 교수님께서 정말 상세하게 진료를 해주셨다. \n진료라기보다는 1:1 과외 교습을 받은 느낌이다.\n\n알레르기 검사를 위해서 피를 굉장히 많이 뽑았다. \n둘째 아들이 괴로워하는 모습을 보는데 너무 안타까웠다.\n\n\n\n\n \n \n 둘째 아토피 치료 관련 기록\n 완치를 위한 관리 방법을 메모한다.\n \n \n \n \n \n \n\n\n\n성남시 여수동 고궁 중국집 방문\n\n\n성남시 여수동 고궁 중국집을 방문했다. \n이전에 전단지만 가지고 블로그를 썼던 적이 있었는데 방문하지도 않은 장소를 블로그에 기록했음에도 불구하고 많은 사람들이 내 글을 보았다. \n둘째 아들 채혈하는 것을 보고 많이 힘들어서 중국집에서 외식을 하기로 했다.\n\n신도림 족발신선생 후기\n\n\n옆집 이웃님께서 퇴근하시면서 족발신선생에서 족발을 포장해주셨다. \n태어나서 먹어 본 족발중에서 손에 꼽을 정도의 맛이었다.\n\n\n\n야들야들하면서도 쫄깃쫄깃한 화덕 족발은 스모키한 냄새가 확 올라왔다. \n불향을 제대로 입혔고 짜지 않아서 마음에 들었다.\n\n\n\n족발과 궁합이 좋은 막국수는 참기름 향이 인상적이었다.\n\n나중에 신도림에 갈 일이 있다면 꼭 다시 들리고 싶은 곳이다.\n"]
Title : 같은 단지에 사는 어린이집 친구들을 우리집에 초대했다. (한솔파 모임)
URL : /diary/2022/11/11/%EC%96%B4%EB%A6%B0%EC%9D%B4%EC%A7%91-%ED%95%99%EB%B6%80%EB%AA%A8-%EB%AA%A8%EC%9E%84-%ED%95%9C%EC%86%94%ED%8C%8C.html
Description : 2022년 11월 11일 일기 (금요일)
Content : 어린이집 학부모 모임(한솔파)
같은 단지에 사는 어린이집 학부모들 모임이 생겼다.
아파트 놀이터에서 같이 놀기도 하고 단지내 편의시설에서 배달 음식도 같이 시켜먹기도 했다.

오늘은 아윤이네와 연우네를 우리집으로 초대해서 연어초을 먹으면서 술한잔했다.
재윤이네 집을 통해서 알게 된 강고집 참맛에서도 음식을 포장해와서 나눠 먹었다.
그동안 출처를 알 수 없었던 중국술을 드디어 해치웠다.

식사 이력




구분
메뉴
비고




아침
 
 


점심
 
회사밥


저녁
연어초밥
한솔파 모임



["어린이집 학부모 모임(한솔파)\n같은 단지에 사는 어린이집 학부모들 모임이 생겼다. \n아파트 놀이터에서 같이 놀기도 하고 단지내 편의시설에서 배달 음식도 같이 시켜먹기도 했다.\n\n오늘은 아윤이네와 연우네를 우리집으로 초대해서 연어초을 먹으면서 술한잔했다. \n재윤이네 집을 통해서 알게 된 강고집 참맛에서도 음식을 포장해와서 나눠 먹었다. \n그동안 출처를 알 수 없었던 중국술을 드디어 해치웠다.\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n  \n  \n \n \n 점심\n  \n 회사밥\n \n \n 저녁\n 연어초밥\n 한솔파 모임\n \n \n\n"]
Title : GitHub Pages Jekyll Liquid에서 for 반복문에 의해 img 테그가 깨지는 현상
URL : /github-pages/2022/11/09/img-tag-broken-workaround-with-figure-tag.html
Description : How to workaround image tag escape problem.
Content : GitHub Pages를 이용해서 본 웹페이지를 운영하고 있다.
Jekyll은 내부적으로 Liquid 문법을 이용하고 있다.
for 반복문과 img 테그를 조합해서 미리 보기 기능을 구현했다.
이유는 알 수 없지만 img 테그가 깨지는 문제가 발생했다.
이 문제점에 대해서 근본 원인은 알 수 없지만, workaround는 있다.

문제 내용 설명

아래는 최근 포스트 5개의 이미지를 보여준다.

코드

{%- for post in site.posts limit:5 %}
{%- if post.image %}
<img style="border-radius: 20px;" src="{{ post.image }}"><br />
{% endif %}
{% endfor %}



또 다른 코드
<a href="/diary/2024/05/13/30%EB%B6%84-%EB%8B%A8%EC%9C%84-%EC%8B%9C%EA%B0%84%EA%B4%80%EB%A6%AC.html"><img style="border-radius: 20px;" src="/assets/images/diary/2023/11/20231123-성남시-고등동-강돈.jpg"></a><br />


<a href="/diary/2023/11/23/%EC%84%B1%EB%82%A8%EC%8B%9C-%EA%B3%A0%EB%93%B1%EB%8F%99-%EA%B3%A0%EA%B9%83%EC%A7%91-%EA%B0%95%EB%8F%88.html"><img style="border-radius: 20px;" src="/assets/images/diary/2023/11/20231123-성남시-고등동-강돈.jpg"></a><br />


<a href="/diary/2022/12/05/%EC%9E%A5%EC%9D%B8%EC%83%81-%EA%B0%90%EC%82%AC-%EC%9D%B8%EC%82%AC.html"><img style="border-radius: 20px;" src="/assets/logo.png"></a><br />


<a href="/diary/2022/12/01/diary.html"><img style="border-radius: 20px;" src="/assets/images/diary/2022/12/01/20221201_184149.jpg"></a><br />


<a href="/diary/2022/11/26/diary.html"><img style="border-radius: 20px;" src="/assets/images/diary/2022/11/26/2022-11-26-13-48-35-303.jpg"></a><br />




실행 결과
<img style="border-radius: 20px;" src="/assets/images/diary/2023/11/20231123-성남시-고등동-강돈.jpg"><br />


<img style="border-radius: 20px;" src="/assets/images/diary/2023/11/20231123-성남시-고등동-강돈.jpg"><br />


<img style="border-radius: 20px;" src="/assets/logo.png"><br />


<img style="border-radius: 20px;" src="/assets/images/diary/2022/12/01/20221201_184149.jpg"><br />


<img style="border-radius: 20px;" src="/assets/images/diary/2022/11/26/2022-11-26-13-48-35-303.jpg"><br />




실제로 생성되는 html 코드를 보면 <img> 부분이 %ltmg>로 깨진 것을 확인할 수 있다.

근본 해결 방법

이 문제의 근본 원인은 아직 모른다.
하지만 workaround 방법은 존재한다.

임시 조치 방법

<img> 테그에 <figure> 테그를 씌우면 테그가 깨지는 문제를 회피할 수 있다.


{%- for post in site.posts limit:5 %}
{%- if post.image %}
<figure><img style="border-radius: 20px;" src="{{ post.image }}"></figure><br />
{% endif %}
{% endfor %}



요약
만약 Jekyll에서 img 테그가 깨지는 문제가 발생한다면,
firure 테그를 img 테그에 씌우면 해결된다.

["GitHub Pages를 이용해서 본 웹페이지를 운영하고 있다. \nJekyll은 내부적으로 Liquid 문법을 이용하고 있다. \nfor 반복문과 img 테그를 조합해서 미리 보기 기능을 구현했다. \n이유는 알 수 없지만 img 테그가 깨지는 문제가 발생했다. \n이 문제점에 대해서 근본 원인은 알 수 없지만, workaround는 있다.\n\n문제 내용 설명\n\n아래는 최근 포스트 5개의 이미지를 보여준다.\n\n코드\n\n{%- for post in site.posts limit:5 %}\n {%- if post.image %}\n <img style=\"border-radius: 20px;\" src=\"{{ post.image }}\"><br />\n {% endif %}\n{% endfor %}\n\n\n\n또 다른 코드\n <a href=\"/diary/2024/05/13/30%EB%B6%84-%EB%8B%A8%EC%9C%84-%EC%8B%9C%EA%B0%84%EA%B4%80%EB%A6%AC.html\"><img style=\"border-radius: 20px;\" src=\"/assets/images/diary/2023/11/20231123-성남시-고등동-강돈.jpg\"></a><br />\n \n\n <a href=\"/diary/2023/11/23/%EC%84%B1%EB%82%A8%EC%8B%9C-%EA%B3%A0%EB%93%B1%EB%8F%99-%EA%B3%A0%EA%B9%83%EC%A7%91-%EA%B0%95%EB%8F%88.html\"><img style=\"border-radius: 20px;\" src=\"/assets/images/diary/2023/11/20231123-성남시-고등동-강돈.jpg\"></a><br />\n \n\n <a href=\"/diary/2022/12/05/%EC%9E%A5%EC%9D%B8%EC%83%81-%EA%B0%90%EC%82%AC-%EC%9D%B8%EC%82%AC.html\"><img style=\"border-radius: 20px;\" src=\"/assets/logo.png\"></a><br />\n \n\n <a href=\"/diary/2022/12/01/diary.html\"><img style=\"border-radius: 20px;\" src=\"/assets/images/diary/2022/12/01/20221201_184149.jpg\"></a><br />\n \n\n <a href=\"/diary/2022/11/26/diary.html\"><img style=\"border-radius: 20px;\" src=\"/assets/images/diary/2022/11/26/2022-11-26-13-48-35-303.jpg\"></a><br />\n \n\n\n\n실행 결과\n <img style=\"border-radius: 20px;\" src=\"/assets/images/diary/2023/11/20231123-성남시-고등동-강돈.jpg\"><br />\n \n\n <img style=\"border-radius: 20px;\" src=\"/assets/images/diary/2023/11/20231123-성남시-고등동-강돈.jpg\"><br />\n \n\n <img style=\"border-radius: 20px;\" src=\"/assets/logo.png\"><br />\n \n\n <img style=\"border-radius: 20px;\" src=\"/assets/images/diary/2022/12/01/20221201_184149.jpg\"><br />\n \n\n <img style=\"border-radius: 20px;\" src=\"/assets/images/diary/2022/11/26/2022-11-26-13-48-35-303.jpg\"><br />\n \n\n\n\n실제로 생성되는 html 코드를 보면 <img> 부분이 %ltmg>로 깨진 것을 확인할 수 있다.\n\n근본 해결 방법\n\n이 문제의 근본 원인은 아직 모른다. \n하지만 workaround 방법은 존재한다.\n\n임시 조치 방법\n\n<img> 테그에 <figure> 테그를 씌우면 테그가 깨지는 문제를 회피할 수 있다.\n\n\n{%- for post in site.posts limit:5 %}\n {%- if post.image %}\n <figure><img style=\"border-radius: 20px;\" src=\"{{ post.image }}\"></figure><br />\n {% endif %}\n{% endfor %}\n\n\n\n요약\n만약 Jekyll에서 img 테그가 깨지는 문제가 발생한다면, \nfirure 테그를 img 테그에 씌우면 해결된다.\n\n"]
Title : 둘째 아토피가 너무 심해서 병원 진료를 봤다.
URL : /diary/2022/11/09/둘째-아토피-병원-진료.html
Description : 2022년 11월 9일 일기
Content : 오늘은 참 많은 일이 있었다.


✅ : 둘째 아토피 심해서 주사 치료 받음
✅ : 직장 어린이집 모임이 있었음
✅ : 상가 구입 고민 관련 부모님과 통화


아침은 아로니아 분말 우유로

요즘 매일 아침마다 우유에 아로니아 분말을 타서 먹는다.
맛도 좋고 건강에도 좋다.
특히 변비에 좋아서 매일 볼일을 보는 편이다.

둘째 아토피 병원 진료

둘째가 어젯밤에 잠을 제대로 자지 못했다.
밤새 체온은 거의 40도까지 근접했고, 신경질적으로 울었다.

오늘 아침 와이프님이 둘째를 데리고 연세지니 소아청소년과에서 진료를 봤다.
아토피가 심하다는 의견으로 심하면 호흡이 곤란할 수 있다고 했다.
얼굴과 눈이 많이 부은 상태였다.


주사를 맞았는데 금방 효과가 있었다.
발진이 금방 가라앉았다.
마치 마법의 주사같은 느낌이었다.
하지만 이 주사는 일시적으로 며칠간 효과가 있을 것이라고 했다.

차병원에서 진료를 볼 수 있도록 소견서를 작성해주셨다.
다음주 월요일 오후 2시에 차병원 진료를 예약했다.

직장 어린이집 모임
연우네, 아윤이네, 규리네, 승원이네 가족이 모였다.
김밥, 떡볶이, 치킨 등을 맛있게 나눠 먹었다.

ASML 김민기님과 통화
ASML로 이직한 KMG 군에게 전화가 왔다.
요즘 우리 회사의 불안한 사정을 알고 전화를 한 느낌이다.
연봉 작은 것 한 장을 덜 받고 입사를 했다고 한다.

부모님과 통화
이모가 오창에 구입해둔 상가가 있는데 유동성이 필요해서 상가를 처분하려 한다고 했다.
공인중개사에 매물을 내놓기 전에 부모님에게 먼저 이야기했다고 한다.

매물 내용




구분
내용
비고




소재지
충북 청주 오창읍
 


구입 비용
약 4.8억
 


보증금
2억
 


월세
180만원
 


실투자비용
 
 


월세율
6.4%
월세/투자비용




투자가 필요한 금액




항목
금액
비고




시세
4.8억
 


보증금
-2억
 


취등록세
2,200만원
4.6%


중개수수료
0원
직접 거래


법무사 비용
20만원
법무통 앱




식사 이력




구분
메뉴
비고




아침
머핀 1개, 아로니아 분말 우유
 


점심
불고기
 


저녁
김밥, 떡볶이, 교촌치킨
길동우동 떡볶이 맛있다



["오늘은 참 많은 일이 있었다.\n\n\n ✅ : 둘째 아토피 심해서 주사 치료 받음\n ✅ : 직장 어린이집 모임이 있었음\n ✅ : 상가 구입 고민 관련 부모님과 통화\n\n\n아침은 아로니아 분말 우유로\n\n요즘 매일 아침마다 우유에 아로니아 분말을 타서 먹는다. \n맛도 좋고 건강에도 좋다. \n특히 변비에 좋아서 매일 볼일을 보는 편이다.\n\n둘째 아토피 병원 진료\n\n둘째가 어젯밤에 잠을 제대로 자지 못했다. \n밤새 체온은 거의 40도까지 근접했고, 신경질적으로 울었다.\n\n오늘 아침 와이프님이 둘째를 데리고 연세지니 소아청소년과에서 진료를 봤다. \n아토피가 심하다는 의견으로 심하면 호흡이 곤란할 수 있다고 했다. \n얼굴과 눈이 많이 부은 상태였다.\n\n\n주사를 맞았는데 금방 효과가 있었다. \n발진이 금방 가라앉았다. \n마치 마법의 주사같은 느낌이었다. \n하지만 이 주사는 일시적으로 며칠간 효과가 있을 것이라고 했다.\n\n차병원에서 진료를 볼 수 있도록 소견서를 작성해주셨다.\n다음주 월요일 오후 2시에 차병원 진료를 예약했다.\n\n직장 어린이집 모임\n연우네, 아윤이네, 규리네, 승원이네 가족이 모였다. \n김밥, 떡볶이, 치킨 등을 맛있게 나눠 먹었다.\n\nASML 김민기님과 통화\nASML로 이직한 KMG 군에게 전화가 왔다. \n요즘 우리 회사의 불안한 사정을 알고 전화를 한 느낌이다. \n연봉 작은 것 한 장을 덜 받고 입사를 했다고 한다.\n\n부모님과 통화\n이모가 오창에 구입해둔 상가가 있는데 유동성이 필요해서 상가를 처분하려 한다고 했다. \n공인중개사에 매물을 내놓기 전에 부모님에게 먼저 이야기했다고 한다.\n\n매물 내용\n\n\n \n \n 구분\n 내용\n 비고\n \n \n \n \n 소재지\n 충북 청주 오창읍\n  \n \n \n 구입 비용\n 약 4.8억\n  \n \n \n 보증금\n 2억\n  \n \n \n 월세\n 180만원\n  \n \n \n 실투자비용\n  \n  \n \n \n 월세율\n 6.4%\n 월세/투자비용\n \n \n\n\n투자가 필요한 금액\n\n\n \n \n 항목\n 금액\n 비고\n \n \n \n \n 시세\n 4.8억\n  \n \n \n 보증금\n -2억\n  \n \n \n 취등록세\n 2,200만원\n 4.6%\n \n \n 중개수수료\n 0원\n 직접 거래\n \n \n 법무사 비용\n 20만원\n 법무통 앱\n \n \n\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 머핀 1개, 아로니아 분말 우유\n  \n \n \n 점심\n 불고기\n  \n \n \n 저녁\n 김밥, 떡볶이, 교촌치킨\n 길동우동 떡볶이 맛있다\n \n \n\n"]
Title : 우분투 리눅스에서 단축키를 이용해서 프로그램을 실행시키는 방법
URL : /ubuntu/2022/11/08/how-to-execute-program-with-shortcut-on-ubuntu.html
Description : How to execute program with shortcut on Ubuntu linux
Content : 단축키가 바로 치트키라고 생각합니다.
어떤 작업이든 마우스를 이용하는 것보다 단축키를 사용하면 훨씬 더 빠르고 효율적입니다.
우분투 리눅스에서 단축키를 이용해서 프로그램을 실행할 수 있습니다.

요약


설정 -> 키보드 -> 바로 가기 보기 및 사용자 설정
키보드 바로 가기에서 바로 가기 사용자 설정
바로 가기 추가
사용자 설정 바로 가기 추가에서 이름, 명령, 바로 가기 추가
등록한 단축키로 프로그램이 실행되는 것을 확인


상세 설명

1. 바로 가기 보기 및 사용자 설정

설정 -> 키보드 -> 바로 가기 보기 및 사용자 설정 메뉴로 들어갑니다.

2. 바로 가기 사용자 설정 선택

키보드 바로 가기 메뉴에서 가장 아래쪽으로 스크롤해보면 바로 가기 사용자 설정 메뉴가 나옵니다.

3. 바로 가기 추가

바로 가기 추가 버튼을 선택합니다.

이름, 명령을 입력

적당한 이름과 명령을 입력한 후에 바로 가기 설정 버튼을 선택합니다.

바로 가기 설정을 눌러 단축키 등록

사용할 단축키를 키보드로 입력합니다.

단축키를 입력해서 테스트

등록한 단축키를 누르면 등록한 프로그램이 자동으로 실행됩니다.

제약 사항

우분투 리눅스에서 단축키로 프로그램을 실행하는데 몇가지 제약사항이 있습니다.
이 점을 주의하시기 바랍니다.


GUI 프로그램만 가능
에러가 발생할 경우 확인이 어려움


GUI 프로그램만 가능

CLI로 제작된 프로그램이나 스크립트는 실행이 불가능합니다.
반드시 GUI로 화면이 뜨는 프로그램이나 스크립트만 실행이 가능합니다.

에러가 발생할 경우 확인이 어려움

GUI로 화면이 뜨는 프로그램을 제작했더라도 프로그램 실행 도중 에러가 발생하면 원인을 확인하기 어렵습니다.
예를 들어, 파이썬으로 tkinter를 이용해서 GUI로 프로그램을 제작했지만 실행 도중에 필요한 모듈을 찾지 못하는 경우가 발생할 수 있습니다.
왜 프로그램이 실행되지 못했는지 확인이 어렵습니다.

이 때는 해당 프로그램이나 스크립트를 쉘에서 실행해보면서 확인하면 됩니다.

$ ./mkpv.py
Traceback (most recent call last):
File "/home/parksejin/project/mkpv/./mkpv.py", line 3, in <module>
from tkinter import *
ModuleNotFoundError: No module named 'tkinter'



위와 같이 쉘에서 프로그래을 실행해보면, 왜 프로그램이 실행되지 못하는지 확인할 수 있습니다.
제 경우는 파이썬 스크립트에서 사용하는 ‘tkinter’라는 모듈을 설치하지 않아서 발행한 문제였네요.



우분투 리눅스에서 단축키를 등록할 때 도움이 되는 팁들을 소개합니다.

파이썬 스크립트 자동 실행하는 방법

파이썬 스크립트는 쉐뱅을 이용하면 실행 파일을 만들지 않아도 실행 가능합니다.






파이썬 스크립트 자동실행 방법 (#!/usr/bin/env python3)
파이썬을 처음 시작했을 때는 파이썬 스크립트를 실행시킬 때마다 python 혹은 python3 명령을 붙여주었다. 하지만 파이썬에 어느 정도 익숙해진 지금은 shebang(셔뱅)을 이용해서 파이썬 스크립트를 자동으로 실행될 수 있도록 작성하고 있다. 셔뱅(shebang)이란? 셔뱅(shebang)이라는 것이 처음에는 조금 낯설 수 있겠다. 하지만 우리는 이미 습관적으로 셔뱅을 구사하고 있다. 우리가 bash script를 작성할 때 아주 습관적으로 가장 첫 번째 줄에 #!/bin/bash를 입력한다. 마찬가지로 파이썬 스크립트에 #!/usr/bin/env python3 구문을 입력하면 쉘은 알아서 python3를 실행하여 해당 스크립트를 수행한다. 배쉬 스크립트 셔뱅 예제 (script.sh) #!/bi..









단축키가 중복될 경우 다른 단축키 사용



만약 사용하려는 단축키가 이미 사용중이면 아래와 같이 다른 용도로 사용중이라는 것을 확인할 수 있습니다.


Alt+Print은(는) 창의 스크린샷 찍기 용도로 사용 중입니다. 바꾸면 창의 스크린샷 찍기이(가) 사용 중지됩니다.


이 때는 다른 단축키로 변경해서 등록하면 됩니다.
["단축키가 바로 치트키라고 생각합니다. \n어떤 작업이든 마우스를 이용하는 것보다 단축키를 사용하면 훨씬 더 빠르고 효율적입니다. \n우분투 리눅스에서 단축키를 이용해서 프로그램을 실행할 수 있습니다.\n\n요약\n\n\n 설정 -> 키보드 -> 바로 가기 보기 및 사용자 설정\n 키보드 바로 가기에서 바로 가기 사용자 설정\n 바로 가기 추가\n 사용자 설정 바로 가기 추가에서 이름, 명령, 바로 가기 추가\n 등록한 단축키로 프로그램이 실행되는 것을 확인\n\n\n상세 설명\n\n1. 바로 가기 보기 및 사용자 설정\n\n설정 -> 키보드 -> 바로 가기 보기 및 사용자 설정 메뉴로 들어갑니다.\n\n2. 바로 가기 사용자 설정 선택\n\n키보드 바로 가기 메뉴에서 가장 아래쪽으로 스크롤해보면 바로 가기 사용자 설정 메뉴가 나옵니다.\n\n3. 바로 가기 추가\n\n바로 가기 추가 버튼을 선택합니다.\n\n이름, 명령을 입력\n\n적당한 이름과 명령을 입력한 후에 바로 가기 설정 버튼을 선택합니다.\n\n바로 가기 설정을 눌러 단축키 등록\n\n사용할 단축키를 키보드로 입력합니다.\n\n단축키를 입력해서 테스트\n\n등록한 단축키를 누르면 등록한 프로그램이 자동으로 실행됩니다.\n\n제약 사항\n\n우분투 리눅스에서 단축키로 프로그램을 실행하는데 몇가지 제약사항이 있습니다. \n이 점을 주의하시기 바랍니다.\n\n\n GUI 프로그램만 가능\n 에러가 발생할 경우 확인이 어려움\n\n\nGUI 프로그램만 가능\n\nCLI로 제작된 프로그램이나 스크립트는 실행이 불가능합니다. \n반드시 GUI로 화면이 뜨는 프로그램이나 스크립트만 실행이 가능합니다.\n\n에러가 발생할 경우 확인이 어려움\n\nGUI로 화면이 뜨는 프로그램을 제작했더라도 프로그램 실행 도중 에러가 발생하면 원인을 확인하기 어렵습니다. \n예를 들어, 파이썬으로 tkinter를 이용해서 GUI로 프로그램을 제작했지만 실행 도중에 필요한 모듈을 찾지 못하는 경우가 발생할 수 있습니다. \n왜 프로그램이 실행되지 못했는지 확인이 어렵습니다.\n\n이 때는 해당 프로그램이나 스크립트를 쉘에서 실행해보면서 확인하면 됩니다.\n\n$ ./mkpv.py \nTraceback (most recent call last):\n File \"/home/parksejin/project/mkpv/./mkpv.py\", line 3, in <module>\n from tkinter import *\nModuleNotFoundError: No module named 'tkinter'\n\n\n\n위와 같이 쉘에서 프로그래을 실행해보면, 왜 프로그램이 실행되지 못하는지 확인할 수 있습니다. \n제 경우는 파이썬 스크립트에서 사용하는 ‘tkinter’라는 모듈을 설치하지 않아서 발행한 문제였네요.\n\n팁\n\n우분투 리눅스에서 단축키를 등록할 때 도움이 되는 팁들을 소개합니다.\n\n파이썬 스크립트 자동 실행하는 방법\n\n파이썬 스크립트는 쉐뱅을 이용하면 실행 파일을 만들지 않아도 실행 가능합니다.\n\n\n\n\n \n \n 파이썬 스크립트 자동실행 방법 (#!/usr/bin/env python3)\n 파이썬을 처음 시작했을 때는 파이썬 스크립트를 실행시킬 때마다 python 혹은 python3 명령을 붙여주었다. 하지만 파이썬에 어느 정도 익숙해진 지금은 shebang(셔뱅)을 이용해서 파이썬 스크립트를 자동으로 실행될 수 있도록 작성하고 있다. 셔뱅(shebang)이란? 셔뱅(shebang)이라는 것이 처음에는 조금 낯설 수 있겠다. 하지만 우리는 이미 습관적으로 셔뱅을 구사하고 있다. 우리가 bash script를 작성할 때 아주 습관적으로 가장 첫 번째 줄에 #!/bin/bash를 입력한다. 마찬가지로 파이썬 스크립트에 #!/usr/bin/env python3 구문을 입력하면 쉘은 알아서 python3를 실행하여 해당 스크립트를 수행한다. 배쉬 스크립트 셔뱅 예제 (script.sh) #!/bi..\n \n \n \n \n \n \n\n\n\n단축키가 중복될 경우 다른 단축키 사용\n\n\n\n만약 사용하려는 단축키가 이미 사용중이면 아래와 같이 다른 용도로 사용중이라는 것을 확인할 수 있습니다.\n\n\n Alt+Print은(는) 창의 스크린샷 찍기 용도로 사용 중입니다. 바꾸면 창의 스크린샷 찍기이(가) 사용 중지됩니다.\n\n\n이 때는 다른 단축키로 변경해서 등록하면 됩니다.\n"]
Title : 도대체 무엇을 했는지 모르겠는 하루다. 기록이 그만큼 중요하다.
URL : /diary/2022/11/08/%EB%8F%84%EB%8C%80%EC%B2%B4-%EB%AC%B4%EC%97%87%EC%9D%84-%ED%96%88%EB%8A%94%EC%A7%80-%EB%AA%A8%EB%A5%B4%EA%B2%A0%EB%8A%94-%ED%95%98%EB%A3%A8.html
Description : 2022년 11월 8일 일기
Content : 점심에 먹은 식사 사진을 찍지 않았더라면 하루동안 무엇을 했는지 알 수 없었을 것이다.
기록이 그만큼 중요하다.

파이썬 mkinter로 GUI 프로그래밍
요즘 파이썬 mkinter 패키지를 이용해서 GUI 프로그래밍을 익히고 있다.
큰 어려움 없이 내가 원하는 프로그램을 만들어서 편리하게 사용 중이다.
파이썬으로 내가 원하는 프로그램을 만들고, 우분투 리눅스에서 단축키를 등록했다.
CTRL와 F1를 누르면 내가 작성한 파이썬 스크립트가 자동으로 실행되도록 설정했다.
몹시 편하다.






우분투 리눅스에서 단축키를 이용해서 프로그램을 실행시키는 방법
How to execute program with shortcut on Ubuntu linux









식사 이력





구분
메뉴
비고




아침
 
 


점심
김치볶음밥
회사밥


저녁
 
 



["점심에 먹은 식사 사진을 찍지 않았더라면 하루동안 무엇을 했는지 알 수 없었을 것이다. \n기록이 그만큼 중요하다.\n\n파이썬 mkinter로 GUI 프로그래밍\n요즘 파이썬 mkinter 패키지를 이용해서 GUI 프로그래밍을 익히고 있다. \n큰 어려움 없이 내가 원하는 프로그램을 만들어서 편리하게 사용 중이다. \n파이썬으로 내가 원하는 프로그램을 만들고, 우분투 리눅스에서 단축키를 등록했다. \nCTRL와 F1를 누르면 내가 작성한 파이썬 스크립트가 자동으로 실행되도록 설정했다. \n몹시 편하다.\n\n\n\n\n \n \n 우분투 리눅스에서 단축키를 이용해서 프로그램을 실행시키는 방법\n How to execute program with shortcut on Ubuntu linux\n \n \n \n \n \n \n\n\n\n식사 이력\n\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n  \n  \n \n \n 점심\n 김치볶음밥\n 회사밥\n \n \n 저녁\n  \n  \n \n \n\n"]
Title : 22년 11월 06일 일기
URL : /diary/2022/11/06/diary.html
Description : 22년 11월 06일 일기
Content :
["\n"]
Title : 세차하다가 지갑 찾음, 호계시장 원조왕족발 호계반찬, 승주네가 우리집에 놀러왔다.
URL : /diary/2022/11/06/%ED%98%B8%EA%B3%84%EC%8B%9C%EC%9E%A5-%EC%9B%90%EC%A1%B0%EC%99%95%EC%A1%B1%EB%B0%9C-%EC%8A%B9%EC%A3%BC%EB%84%A4-%EB%86%80%EB%9F%AC%EC%98%B4.html
Description : 2022년 11월 6일 일기
Content : 몹시 기분 좋은 날이다.
셀프 세차를 하다가 지갑을 찾았다.
호계시장에서 가성비 족발 맛집도 발굴했다.
승주네가 우리집에 놀러왔다.

요약

✅ 킹콩샤워 안양직영점에서 세차
✅ 장인어른 댁에 방문
✅ 호계시장 원조왕족발에서 족발 구입
✅ 승주네가 우리집에 놀러 옴


킹콩샤워 안양직영점에서 세차

레이가 너무 더러워서 킹콩샤워 안양직영점에서 세차를 했다.
세차 도중에 트렁크 안쪽에서 잃어버렸던 지갑을 찾았다.
8월에 지갑을 잃어버려서 제법 속상해했다.
속상했던 마음보다 훨씬 더 큰 행복감을 느꼈다.

킹콩샤워 안양직영점






킹콩샤워 안양직영점 · 경기도 군포시 금정동 214-2
★★★★★ · 셀프 세차장









장인어른 댁에 방문
세차를 마치고 장인어른 댁에 방문을 했다.
소고기 수육과 파김치를 맛있게 먹었다.
장인어른께서는 항암치료중이셔서 머리카락이 모두 빠져있었다.
마음이 좋지 못하다.

호계시장 원조왕족발

저녁에 승주네에서 우리집에 놀러오기로 했다.
항상 연어초밥만 대접하다보니 물릴 것 같아서 새로운 메뉴를 생각해냈다.
호계시장에서 족발을 구입해서 손님을 대접하기로 결정했다.

호계시장에 있는 원조왕족발이라는 곳에서 구입한 족발은 가격이 저렴하면서도 푸짐했다.
성인 4명이 배부르게 식사할 수 있는 충분한 양으로 가성비가 좋았다.
쌈채소, 쌈장, 새우젓 등도 다양하게 챙겨주셨다.
잘 기억해뒀다가 다음에도 또 구입할 생각이다.


족발(대) 가격 : 2.4만원


호계시장 원조왕족발






원조미니왕족발 · 경기도 안양시 동안구 호계1동 995-14
★★★★★ · 족발/보쌈집









승주네가 우리집에 놀러왔다.
성남으로 이사 온지 거의 4개월이 다 되어간다.
그러고보니 승주네를 한 번도 초대한 적이 없었다.
오늘 승주네에서 놀러왔다.
아이들이 많이 컸는지 싸우지 않고 사이좋게 잘 지냈다.

집뜰이 선물로 키친타올과 에그타르트를 가져오셨다.
직접 만든 에그타르트는 정말 맛이 좋았다.

식사 이력




구분
메뉴
비고




아침
돼지고기 구이
 


점심
소고기 수육 + 파김치
 


저녁
호계시장 원조왕족발
포장




["몹시 기분 좋은 날이다. \n셀프 세차를 하다가 지갑을 찾았다. \n호계시장에서 가성비 족발 맛집도 발굴했다. \n승주네가 우리집에 놀러왔다.\n\n요약\n\n ✅ 킹콩샤워 안양직영점에서 세차\n ✅ 장인어른 댁에 방문\n ✅ 호계시장 원조왕족발에서 족발 구입\n ✅ 승주네가 우리집에 놀러 옴\n\n\n킹콩샤워 안양직영점에서 세차\n\n레이가 너무 더러워서 킹콩샤워 안양직영점에서 세차를 했다. \n세차 도중에 트렁크 안쪽에서 잃어버렸던 지갑을 찾았다. \n8월에 지갑을 잃어버려서 제법 속상해했다. \n속상했던 마음보다 훨씬 더 큰 행복감을 느꼈다.\n\n킹콩샤워 안양직영점\n\n\n\n\n \n \n 킹콩샤워 안양직영점 · 경기도 군포시 금정동 214-2\n ★★★★★ · 셀프 세차장\n \n \n \n \n \n \n\n\n\n장인어른 댁에 방문\n세차를 마치고 장인어른 댁에 방문을 했다. \n소고기 수육과 파김치를 맛있게 먹었다. \n장인어른께서는 항암치료중이셔서 머리카락이 모두 빠져있었다. \n마음이 좋지 못하다.\n\n호계시장 원조왕족발\n\n저녁에 승주네에서 우리집에 놀러오기로 했다. \n항상 연어초밥만 대접하다보니 물릴 것 같아서 새로운 메뉴를 생각해냈다. \n호계시장에서 족발을 구입해서 손님을 대접하기로 결정했다.\n\n호계시장에 있는 원조왕족발이라는 곳에서 구입한 족발은 가격이 저렴하면서도 푸짐했다. \n성인 4명이 배부르게 식사할 수 있는 충분한 양으로 가성비가 좋았다. \n쌈채소, 쌈장, 새우젓 등도 다양하게 챙겨주셨다. \n잘 기억해뒀다가 다음에도 또 구입할 생각이다.\n\n\n 족발(대) 가격 : 2.4만원\n\n\n호계시장 원조왕족발\n\n\n\n\n \n \n 원조미니왕족발 · 경기도 안양시 동안구 호계1동 995-14\n ★★★★★ · 족발/보쌈집\n \n \n \n \n \n \n\n\n\n승주네가 우리집에 놀러왔다.\n성남으로 이사 온지 거의 4개월이 다 되어간다. \n그러고보니 승주네를 한 번도 초대한 적이 없었다. \n오늘 승주네에서 놀러왔다. \n아이들이 많이 컸는지 싸우지 않고 사이좋게 잘 지냈다.\n\n집뜰이 선물로 키친타올과 에그타르트를 가져오셨다. \n직접 만든 에그타르트는 정말 맛이 좋았다.\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 돼지고기 구이\n  \n \n \n 점심\n 소고기 수육 + 파김치\n  \n \n \n 저녁\n 호계시장 원조왕족발\n 포장\n \n \n\n\n"]
Title : 재윤이네 집뜰이, 강고집참맛, 판교현대백화점, 회전목마
URL : /diary/2022/11/05/%EC%9E%AC%EC%9C%A4%EC%9D%B4%EB%84%A4-%EC%A7%91%EB%9C%B0%EC%9D%B4.html
Description : 2022년 11월 5일 일기
Content : 재윤이네가 지난달 판교로 이사를 갔다.
집뜰이를 다녀왔다.
두루마리 휴지와 책과 직접 만든 빼빼로를 가져갔다.

선물로 가져간 책은 오리고 붙이고 세우는 한국사 플랩북 한국을 빛낸 100명의 위인들이라는 책이다.
다락원에서 나온 책이고 정가는 1.6만원이다.

요약

✅ 재윤이네 판교 집뜰이
✅ 판교에 강고집참맛이라는 맛집이 있다. :exclamation:
✅ 판교백화점 옥상에서 놀고 5층 회전목마 이용


판교 맛집 ‘강고집참맛’
재윤이네에 가보니 점심상이 푸짐했다.
보쌈, 보쌈김치, 계란말이, 전, 도토리묵, 청국장 등 다양하게 준비되어 있었다.
많은 음식들이 준비되어 있어서 부담스러웠다.
알고보니 강고집참맛이라는 맛집에서 구입해온 음식들이었다.

1인분에 1.3만원인데 보쌈, 밥, 반찬, 국 등이 포함되어 있다.
맛도 좋고 가격도 착해서 잘 기억해뒀다가 다음에도 꼭 이용할 생각이다.






강고집참맛 : 네이버
방문자리뷰 228 · 블로그리뷰 19









판교 현대백화점 옥상 + 5층 회전목마

오랜만에 현대백화점 판교점을 다녀왔다.
10층 옥상정원에서 한참을 뛰어 놀았다.
놀라운 사실은 여기서 어린이집 친구인 서진이네를 만났다는 것이다.

10층에서 논 후에는 5층에서 회전목마를 탔다.
회전목마 이용 가격은 2천원이다.

마지막으로 지하에 있는 푸드코트에서 베스킨라빈스 콘을 음미하는 것으로 하루 일과를 마무리 했다.

식사 이력




구분
메뉴
비고




아침
열라면
 


점심
강고집참맛
포장


저녁
쌀밥, 파김치, 만두
 




지출




항목
비용
사용처
비고




회전목마
2,000원
판교현대백화점 5층
(주)키즈써클




["재윤이네가 지난달 판교로 이사를 갔다. \n집뜰이를 다녀왔다. \n두루마리 휴지와 책과 직접 만든 빼빼로를 가져갔다.\n\n선물로 가져간 책은 오리고 붙이고 세우는 한국사 플랩북 한국을 빛낸 100명의 위인들이라는 책이다. \n다락원에서 나온 책이고 정가는 1.6만원이다.\n\n요약\n\n ✅ 재윤이네 판교 집뜰이\n ✅ 판교에 강고집참맛이라는 맛집이 있다. :exclamation:\n ✅ 판교백화점 옥상에서 놀고 5층 회전목마 이용\n\n\n판교 맛집 ‘강고집참맛’\n재윤이네에 가보니 점심상이 푸짐했다. \n보쌈, 보쌈김치, 계란말이, 전, 도토리묵, 청국장 등 다양하게 준비되어 있었다. \n많은 음식들이 준비되어 있어서 부담스러웠다. \n알고보니 강고집참맛이라는 맛집에서 구입해온 음식들이었다.\n\n1인분에 1.3만원인데 보쌈, 밥, 반찬, 국 등이 포함되어 있다. \n맛도 좋고 가격도 착해서 잘 기억해뒀다가 다음에도 꼭 이용할 생각이다.\n\n\n\n\n \n \n 강고집참맛 : 네이버\n 방문자리뷰 228 · 블로그리뷰 19\n \n \n \n \n \n \n\n\n\n판교 현대백화점 옥상 + 5층 회전목마\n\n오랜만에 현대백화점 판교점을 다녀왔다. \n10층 옥상정원에서 한참을 뛰어 놀았다. \n놀라운 사실은 여기서 어린이집 친구인 서진이네를 만났다는 것이다.\n\n10층에서 논 후에는 5층에서 회전목마를 탔다. \n회전목마 이용 가격은 2천원이다.\n\n마지막으로 지하에 있는 푸드코트에서 베스킨라빈스 콘을 음미하는 것으로 하루 일과를 마무리 했다.\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 열라면\n  \n \n \n 점심\n 강고집참맛\n 포장\n \n \n 저녁\n 쌀밥, 파김치, 만두\n  \n \n \n\n\n지출\n\n\n \n \n 항목\n 비용\n 사용처\n 비고\n \n \n \n \n 회전목마\n 2,000원\n 판교현대백화점 5층\n (주)키즈써클\n \n \n\n\n"]
Title : GitHub Pages에 방문자수 카운터 표시하는 방법 (feat. hits.sh)
URL : /github-pages/2022/11/04/how-to-count-visitors-on-github-pages.html
Description : 깃허브 페이지스 블로그에 방문자수 카운터 표시하는 방법
Content : GitHub Pages는 분명히 아주 매력적인 무료 웹호스팅 서비스이다.
markdown 문법으로 시원시원하게 글을 작성할 수 있고,
구글 애드센스를 연동하여 수익형 블로그로 만들 수 있다.
장점을 이야기하자면 너무 많아서 손가락이 아프다.

단점도 몇 가지 있다.
정적인 웹서버이기 때문에 방문자수 카운트가 불가하다.
이를 해결하기 위해서는 카운터 서비스를 이용해야 한다.

GitHub Pages에 사용할 수 있는 hits.sh 카운터 서비스를 소개한다.

hits.sh 이용

구글 검색을 통해서 발견한 hits.sh 카운터 서비스는 만족스럽다.

장점

깔끔한 디자인
가입 필요 없이 손쉽게 사용 가능
무료 서비스


단점

페이지를 로딩할때마다 방문자수가 증가한다.


한 사람이 여러번 방문해도 카운터가 증가한다는 것이다.
이 때문에 실제 사용자수보다 더 많은 방문자수가 표시된다.

사용 방법



hits.sh 홈페이지에 방문한다.
블로그 주소를 입력한다.
자동으로 생성된 HTML 테그를 적당한 곳에 활용한다.


페이지별로 방문자 확인
Jekyll의 Liquid 문법을 조금 응용하면 페이지별로 방문자 카운터를 달 수 있다.


{% assign url = site.url | remove_first: "https://" | append: page.url %}
<a href="https://hits.sh/{{ url }}/"><img alt="Hits" style="border: 0px; margin: 0px;" src="https://hits.sh/{{ url }}.svg?view=today-total"/></a>



예를 들어 https://boyinblue.github.io/about/ 페이지에 카운터를 달아보자.
site.url은 https://boyinblue.github.io이고 page.url은 /about/이다.

remove_first 필터를 이용해서 https://로 시작되는 부분을 제거한다.
그리고 page.url을 append 시키면 boyinblue.github.io/about/이라는 구분자가 완성된다.
이 구분자를 a tag의 href와 img tag의 src에 넣어주면 된다.

홈페이지
아래 홈페이지에서 카운터 서비스를 개설한다.






Hits
Hit Counter for Your GitHub or Any Kind of Websites You Want









관련 페이지
아래 블로그에 더 자세한 내용이 설명되어 있다. hit.sh 서비스를 만든 개발자의 블로그다.






GitHub, 블로그에 방문자 카운터를 달아보자
GitHub 프로필이나 레파지토리, 블로그 등을 방문하다 보면 종종 방문자 카운터가 달린 것을 종종 볼 수 있다.









hit.sh 개발자의 GitHub Repository인데 무슨 내용인지 봐도 잘 모르겠다.






GitHub - silentsoft/hits: Hit Counter for Your GitHub or Any Kind of Websites You Want.
:chart_with_upwards_trend: Hit Counter for Your GitHub or Any Kind of Websites You Want. - GitHub - silentsoft/hits: Hit Counter for Your GitHub or Any Kind of Websites You Want.









도움이 될만한 페이지들

GitHub Pages에 댓글 기능 활성화 방법






Github Pages에 giscus 연동하는 방법
How to embed discussion on the GitHub pages.








["GitHub Pages는 분명히 아주 매력적인 무료 웹호스팅 서비스이다. \nmarkdown 문법으로 시원시원하게 글을 작성할 수 있고, \n구글 애드센스를 연동하여 수익형 블로그로 만들 수 있다. \n장점을 이야기하자면 너무 많아서 손가락이 아프다.\n\n단점도 몇 가지 있다. \n정적인 웹서버이기 때문에 방문자수 카운트가 불가하다. \n이를 해결하기 위해서는 카운터 서비스를 이용해야 한다.\n\nGitHub Pages에 사용할 수 있는 hits.sh 카운터 서비스를 소개한다.\n\nhits.sh 이용\n\n구글 검색을 통해서 발견한 hits.sh 카운터 서비스는 만족스럽다.\n\n장점\n\n 깔끔한 디자인\n 가입 필요 없이 손쉽게 사용 가능\n 무료 서비스\n\n\n단점\n\n 페이지를 로딩할때마다 방문자수가 증가한다.\n\n\n한 사람이 여러번 방문해도 카운터가 증가한다는 것이다. \n이 때문에 실제 사용자수보다 더 많은 방문자수가 표시된다.\n\n사용 방법\n\n\n\n hits.sh 홈페이지에 방문한다.\n 블로그 주소를 입력한다.\n 자동으로 생성된 HTML 테그를 적당한 곳에 활용한다.\n\n\n페이지별로 방문자 확인\nJekyll의 Liquid 문법을 조금 응용하면 페이지별로 방문자 카운터를 달 수 있다.\n\n\n{% assign url = site.url | remove_first: \"https://\" | append: page.url %}\n\"Hits\"\n\n\n\n예를 들어 https://boyinblue.github.io/about/ 페이지에 카운터를 달아보자. \nsite.url은 https://boyinblue.github.io이고 page.url은 /about/이다.\n\nremove_first 필터를 이용해서 https://로 시작되는 부분을 제거한다. \n그리고 page.url을 append 시키면 boyinblue.github.io/about/이라는 구분자가 완성된다. \n이 구분자를 a tag의 href와 img tag의 src에 넣어주면 된다.\n\n홈페이지\n아래 홈페이지에서 카운터 서비스를 개설한다.\n\n\n\n\n \n \n Hits\n Hit Counter for Your GitHub or Any Kind of Websites You Want\n \n \n \n \n \n \n\n\n\n관련 페이지\n아래 블로그에 더 자세한 내용이 설명되어 있다. hit.sh 서비스를 만든 개발자의 블로그다.\n\n\n\n\n \n \n GitHub, 블로그에 방문자 카운터를 달아보자\n GitHub 프로필이나 레파지토리, 블로그 등을 방문하다 보면 종종 방문자 카운터가 달린 것을 종종 볼 수 있다.\n \n \n \n \n \n \n\n\n\nhit.sh 개발자의 GitHub Repository인데 무슨 내용인지 봐도 잘 모르겠다.\n\n\n\n\n \n \n GitHub - silentsoft/hits: Hit Counter for Your GitHub or Any Kind of Websites You Want.\n :chart_with_upwards_trend: Hit Counter for Your GitHub or Any Kind of Websites You Want. - GitHub - silentsoft/hits: Hit Counter for Your GitHub or Any Kind of Websites You Want.\n \n \n \n \n \n \n\n\n\n도움이 될만한 페이지들\n\nGitHub Pages에 댓글 기능 활성화 방법\n\n\n\n\n \n \n Github Pages에 giscus 연동하는 방법\n How to embed discussion on the GitHub pages.\n \n \n \n \n \n \n\n\n"]
Title : 알뜰요금제 개통, 신장개업 가마치통닭, 컴포즈커피 얼그레이, 아로니아 우유
URL : /diary/2022/11/04/%EC%95%8C%EB%9C%B0%EC%9A%94%EA%B8%88%EC%A0%9C%EA%B0%9C%ED%86%B5-%EA%B0%80%EB%A7%88%EC%B9%98%ED%86%B5%EB%8B%AD-%EC%BB%B4%ED%8F%AC%EC%A6%88%EC%BB%A4%ED%94%BC.html
Description : 2022년 11월 4일 일기
Content : 회사에서 전체 인력의 40%를 희망퇴직 시키겠다고 선언한지 이틀째다.
사무실 분위기는 상당히 좋지 않다.
좋지 않은 상황이지만 업무를 어느정도 처리했다.


✅ 쾌변을 부르는 아로니아 우유
✅ 컴포즈 커피에서 얼그레이 한 잔
✅ 스마트폰 알뜰요금제 개통 완료
✅ 가마치 통닭에서 간장 콤보 치킨 구입


만족스러운 아로니아 우유 :smile:

아침에 집에서 아로니아 우유를 마셨다.
동결 건조된 아로니아 분말을 우유와 섞었다.
이것은 간편하면서도 건강한 아침 대용식이다.

똥이 잘 나왔다.
사무실에서 응가 신호가 와서 화장실을 갔다.
기분 좋은 쾌변이었다.
아로니아 우유 덕분이라고 생각된다.

컴포즈커피 :tea:


사무실 분위기가 좋지 않아서 동료와 함께 카페에 갔다.

알뜰요금제 개통 완료 :iphone:
알뜰요금제 유심을 구입한지 5일만에 스마트폰이 개통되었다.
나는 유플러스 호갱이었다.
월 1만원도 안 되는 요금이 상당히 매력적이다.

가마치통닭 :poultry_leg:
집 근처에 치킨집이 새로 생겼다.
가마치 통닭이라는 치킨집이다.
오픈한지 이틀째인 날에 방문했다.

간장 콤보 치킨은 1.7만원에 구입했다.
육질과 기름이 신선했다.






성남 고등동 신장개업 치킨집 《가마치 성남고등점》 오픈 이벤트 좋다♡
요즘 마음을 다잡기가 힘들다. 좀처럼 회사 일에 집중하기 어렵다. 같이 일하는 동료들 모두 같은 심정이다...









식사 이력




구분
메뉴
비고




아침
아로니아 우유
 


점심
짜장면
 


저녁
간장 치킨 콤보
가마치 통닭



["회사에서 전체 인력의 40%를 희망퇴직 시키겠다고 선언한지 이틀째다. \n사무실 분위기는 상당히 좋지 않다. \n좋지 않은 상황이지만 업무를 어느정도 처리했다.\n\n\n ✅ 쾌변을 부르는 아로니아 우유\n ✅ 컴포즈 커피에서 얼그레이 한 잔\n ✅ 스마트폰 알뜰요금제 개통 완료\n ✅ 가마치 통닭에서 간장 콤보 치킨 구입\n\n\n만족스러운 아로니아 우유 :smile:\n\n아침에 집에서 아로니아 우유를 마셨다. \n동결 건조된 아로니아 분말을 우유와 섞었다. \n이것은 간편하면서도 건강한 아침 대용식이다.\n\n똥이 잘 나왔다. \n사무실에서 응가 신호가 와서 화장실을 갔다. \n기분 좋은 쾌변이었다. \n아로니아 우유 덕분이라고 생각된다.\n\n컴포즈커피 :tea:\n\n\n사무실 분위기가 좋지 않아서 동료와 함께 카페에 갔다.\n\n알뜰요금제 개통 완료 :iphone:\n알뜰요금제 유심을 구입한지 5일만에 스마트폰이 개통되었다. \n나는 유플러스 호갱이었다. \n월 1만원도 안 되는 요금이 상당히 매력적이다.\n\n가마치통닭 :poultry_leg:\n집 근처에 치킨집이 새로 생겼다. \n가마치 통닭이라는 치킨집이다. \n오픈한지 이틀째인 날에 방문했다.\n\n간장 콤보 치킨은 1.7만원에 구입했다. \n육질과 기름이 신선했다.\n\n\n\n\n \n \n 성남 고등동 신장개업 치킨집 《가마치 성남고등점》 오픈 이벤트 좋다♡\n 요즘 마음을 다잡기가 힘들다. 좀처럼 회사 일에 집중하기 어렵다. 같이 일하는 동료들 모두 같은 심정이다...\n \n \n \n \n \n \n\n\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 아로니아 우유\n  \n \n \n 점심\n 짜장면\n  \n \n \n 저녁\n 간장 치킨 콤보\n 가마치 통닭\n \n \n\n"]
Title : 우분투 리눅스에서 펌웨어 업그레이드 방법
URL : /ubuntu/2022/11/03/how-to-firmware-upgrade-on-ubuntu.html
Description : 2 devices have a firmware upgrade available.
Content : ssh를 이용해서 우부투 서버에 접속을 했다.
아래와 같은 메시지를 발견했다.

2 devices have a firmware upgrade available.
Run 'fwupdmgr get-upgrades' for more information.


장치에 업그레이드할 수 있는 새로운 펌웨어가 발행된 것으로 보인다.
fwupdmgr get-upgrades 명령을 통해서 더 많은 정보를 얻을 수 있다고 한다.

fwupdmgr get-upgrades

아래의 명령을 실행해보면 업그레이드 관련된 내용이 잔뜩 표시되기만하고 업그레이드를 할 수는 없다.

$ sudo fwupdmgr get-upgrades


업그레이드 명령

업그레이드를 위해서는 아래의 명령을 실행하면 된다.
중간에 Y나 N 등을 선택해줘야 한다.

$ sudo fwupdmgr update


업그레이드가 완료된 이후에 재부팅이 필요할 수 있다.
["ssh를 이용해서 우부투 서버에 접속을 했다. \n아래와 같은 메시지를 발견했다.\n\n2 devices have a firmware upgrade available.\nRun 'fwupdmgr get-upgrades' for more information.\n\n\n장치에 업그레이드할 수 있는 새로운 펌웨어가 발행된 것으로 보인다. \nfwupdmgr get-upgrades 명령을 통해서 더 많은 정보를 얻을 수 있다고 한다.\n\nfwupdmgr get-upgrades\n\n아래의 명령을 실행해보면 업그레이드 관련된 내용이 잔뜩 표시되기만하고 업그레이드를 할 수는 없다.\n\n$ sudo fwupdmgr get-upgrades\n\n\n업그레이드 명령\n\n업그레이드를 위해서는 아래의 명령을 실행하면 된다. \n중간에 Y나 N 등을 선택해줘야 한다.\n\n$ sudo fwupdmgr update\n\n\n업그레이드가 완료된 이후에 재부팅이 필요할 수 있다.\n"]
Title : 군마트 제품 리뷰
URL : /px/2022/11/03/%EA%B5%B0%EB%A7%88%ED%8A%B8-%EC%95%84%EB%A7%9D%EB%93%9C%EC%BB%A4%ED%94%BC-%EA%B0%80%EA%B2%A9-%EB%B0%8F-%EB%A6%AC%EB%B7%B0.html
Description : PX에서 판매하는 제품들의 가격과 리뷰를 기록합니다.
Content : 비상근 예비군은 전국에 있는 영외 군마트를 이용할 수 있습니다.
군인이나 국가유공자가 아니지만 국군복지단에서 판매하는 제품들을 저렴하게 구입할 수 있습니다.
OO사단 PX에서 구입한 아망드커피라는 쿠키에 대해 리뷰합니다.

구입 가격(1,150원)

2022년 10월15일에 XX사단 PX에서 1,150원에 구입했습니다.


아망드 커피는 금촌베이커리에서 생산한 제품입니다.
비슷한 제품으로는 아망드 쇼콜라와 샤르로스 쿠키가 있습니다.

샤르로스 쿠키 리뷰






군마트에서만 판매하는 새로운 과자 샤르로스 쿠키 (1,180원)
필자는 비상근 예비군입니다. 휴일 훈련을 하루 참여하면 15만 원에 해당하는 훈련 보상비를 받을 수 있습니다. 또한 전국에 있는 영외 군마트를 이용할 수 있는 혜택이 있습니다. 주말에 비상근 예비군 훈련을 갈때마다 평소에서 맛보지 못했던 과자들을 사 와서 아들에게 바치곤 합니다. 이번에 구입한 샤르로스 쿠키는 대형마트, 슈퍼마켓, 편의점 등에서 한 번도 접하지 못했던 새로운 과자였습니다. 결론부터 이야기하자면, 여섯살배기 우리 첫째 아들이 아주 맛있게 먹었습니다. 다음에 훈련을 가게 되면 또 사달라고 하더군요. 금촌베이커리 샤르로스쿠키 우리는 대기업에서 만들어내는 과자들에 익숙해져 있습니다. 대형마트, 슈퍼마켓, 편의점 등에서는 대기업에서 생산하는 과자들을 주로 취급합니다. 반면, 국군복지단에서 운영..










아망드 커피를 포함한 금촌 베이커리의 제품들의 특징은 여러번 나누어서 먹을 수 있도록 뜯는 곳이 있습니다.
그럼에도 불구하고 한 번에 모두 먹어버리게 되는 것 같네요.


아망드커피 쿠키의 크기는 생각보다 작았습니다.
큰 쿠키가 하나 또는 2개 정도 들어있을 것이라고 생각했는데 작은 쿠키가 18개나 들어 있었습니다.


쿠키 1개 크기는 500원짜리 동전 크기보다 조금 더 큽니다.
달콤한 맛에 향긋한 쿠키향이 좋아서 금새 18개를 모두 먹어버렸습니다.
18개에 1,150원이므로 쿠키 1개의 가격은 약 63원입니다.
["비상근 예비군은 전국에 있는 영외 군마트를 이용할 수 있습니다. \n군인이나 국가유공자가 아니지만 국군복지단에서 판매하는 제품들을 저렴하게 구입할 수 있습니다. \nOO사단 PX에서 구입한 아망드커피라는 쿠키에 대해 리뷰합니다.\n\n구입 가격(1,150원)\n\n2022년 10월15일에 XX사단 PX에서 1,150원에 구입했습니다.\n\n\n아망드 커피는 금촌베이커리에서 생산한 제품입니다. \n비슷한 제품으로는 아망드 쇼콜라와 샤르로스 쿠키가 있습니다.\n\n샤르로스 쿠키 리뷰\n\n\n\n\n \n \n 군마트에서만 판매하는 새로운 과자 샤르로스 쿠키 (1,180원)\n 필자는 비상근 예비군입니다. 휴일 훈련을 하루 참여하면 15만 원에 해당하는 훈련 보상비를 받을 수 있습니다. 또한 전국에 있는 영외 군마트를 이용할 수 있는 혜택이 있습니다. 주말에 비상근 예비군 훈련을 갈때마다 평소에서 맛보지 못했던 과자들을 사 와서 아들에게 바치곤 합니다. 이번에 구입한 샤르로스 쿠키는 대형마트, 슈퍼마켓, 편의점 등에서 한 번도 접하지 못했던 새로운 과자였습니다. 결론부터 이야기하자면, 여섯살배기 우리 첫째 아들이 아주 맛있게 먹었습니다. 다음에 훈련을 가게 되면 또 사달라고 하더군요. 금촌베이커리 샤르로스쿠키 우리는 대기업에서 만들어내는 과자들에 익숙해져 있습니다. 대형마트, 슈퍼마켓, 편의점 등에서는 대기업에서 생산하는 과자들을 주로 취급합니다. 반면, 국군복지단에서 운영..\n \n \n \n \n \n \n\n\n\n\n아망드 커피를 포함한 금촌 베이커리의 제품들의 특징은 여러번 나누어서 먹을 수 있도록 뜯는 곳이 있습니다. \n그럼에도 불구하고 한 번에 모두 먹어버리게 되는 것 같네요.\n\n\n아망드커피 쿠키의 크기는 생각보다 작았습니다. \n큰 쿠키가 하나 또는 2개 정도 들어있을 것이라고 생각했는데 작은 쿠키가 18개나 들어 있었습니다.\n\n\n쿠키 1개 크기는 500원짜리 동전 크기보다 조금 더 큽니다. \n달콤한 맛에 향긋한 쿠키향이 좋아서 금새 18개를 모두 먹어버렸습니다. \n18개에 1,150원이므로 쿠키 1개의 가격은 약 63원입니다.\n"]
Title : 자바스크립트 임시 파일 저장되는 위치 (Chrome, Edge)
URL : /javascript/2022/11/03/javascript-temporary-file-save-path.html
Description : 자바 스크립트에서 2차원 배열의 선언을 지원하지는 않지만, 약간의 트릭을 이용하여 2차원 배열을 선언할 수 있는 방법을 설명합니다.
Content : 대표적인 정적 웹서비스인 GitHub Pages를 이용해서 본 블로그를 운영하고 있다.
정적 웹페이지는 css로 힘을 줘도 밋밋해 보이는 단점이 있다.
자바스크립트를 이용하면 좀 더 멋지게 블로그를 꾸밀 수 있다.
하지만 js 파일을 수정해서 deploy해도, 웹브라우저에서는 기존에 임시로 다운로드한 js 파일을 그대로 사용하기 때문에
변경한 내용이 제대로 반영되지 못하는 문제가 있다.

쿠키 및 데이터 삭제

인터넷 웹브라우저를 이용할 때, 웹브라우저는 매번 웹버서로부터 웹페이지의 모든 정보를 가져오지는 않는다.
기존에 접속했을 때의 파일과 데이터를 재사용하여 트래픽을 절감하고 속도를 향상시킬 수 있다.

내가 웹서버의 js 파일을 수정하더라도, 웹브라우저는 기존에 다운로드 해 둔 js 파일을 그대로 사용한다.
개발자가 수정해서 새로 배포한 js 파일이 제대로 반영되지 못한다.

이를 해결하기 위해서는 기존 접속시에 임시로 저장해둔 자바스크립트를 지우면 된다.
인터넷 사용 기록을 모두 삭제하면 로컬에 저장된 자바스크립트도 지우기 때문에 이 문제는 해결된다.

모든 접속 기록을 삭제하면 다른 웹페이지에서 임시로 받아둔 파일들도 모두 삭제되기 때문에
웹페이지가 뜨는데 걸리는 시간이 증가한다.


js 파일 저장되는 위치 (Edge 기준)

Microsoft Edge 브라우저를 기준으로 js 파일이 로컬의 어느 경로에 저장되는지 살펴보자.

C:\windows\사용자(계정명)\AppData\Local\Microsoft\Edge\User Data\Default\Code Cache\js


위의 경로에 있는 모든 파일들을 삭제하면 자바스크립트 임시파일들만 삭제할 수 있다.

js 파일 저장되는 위치 (Chrome 기준)

Chrome 브라우저에서 js 파일이 임시 저장되는 경로는 아래와 같다. (우분투 리눅스)

~/.cache/google-chrome/Default/Code Cache/js

["대표적인 정적 웹서비스인 GitHub Pages를 이용해서 본 블로그를 운영하고 있다. \n정적 웹페이지는 css로 힘을 줘도 밋밋해 보이는 단점이 있다. \n자바스크립트를 이용하면 좀 더 멋지게 블로그를 꾸밀 수 있다. \n하지만 js 파일을 수정해서 deploy해도, 웹브라우저에서는 기존에 임시로 다운로드한 js 파일을 그대로 사용하기 때문에 \n변경한 내용이 제대로 반영되지 못하는 문제가 있다.\n\n쿠키 및 데이터 삭제\n\n인터넷 웹브라우저를 이용할 때, 웹브라우저는 매번 웹버서로부터 웹페이지의 모든 정보를 가져오지는 않는다. \n기존에 접속했을 때의 파일과 데이터를 재사용하여 트래픽을 절감하고 속도를 향상시킬 수 있다.\n\n내가 웹서버의 js 파일을 수정하더라도, 웹브라우저는 기존에 다운로드 해 둔 js 파일을 그대로 사용한다. \n개발자가 수정해서 새로 배포한 js 파일이 제대로 반영되지 못한다.\n\n이를 해결하기 위해서는 기존 접속시에 임시로 저장해둔 자바스크립트를 지우면 된다. \n인터넷 사용 기록을 모두 삭제하면 로컬에 저장된 자바스크립트도 지우기 때문에 이 문제는 해결된다.\n\n 모든 접속 기록을 삭제하면 다른 웹페이지에서 임시로 받아둔 파일들도 모두 삭제되기 때문에 \n웹페이지가 뜨는데 걸리는 시간이 증가한다.\n\n\njs 파일 저장되는 위치 (Edge 기준)\n\nMicrosoft Edge 브라우저를 기준으로 js 파일이 로컬의 어느 경로에 저장되는지 살펴보자.\n\n C:\\windows\\사용자(계정명)\\AppData\\Local\\Microsoft\\Edge\\User Data\\Default\\Code Cache\\js\n\n\n위의 경로에 있는 모든 파일들을 삭제하면 자바스크립트 임시파일들만 삭제할 수 있다.\n\njs 파일 저장되는 위치 (Chrome 기준)\n\nChrome 브라우저에서 js 파일이 임시 저장되는 경로는 아래와 같다. (우분투 리눅스)\n\n ~/.cache/google-chrome/Default/Code Cache/js\n\n"]
Title : HTML5 Style에 대한 내용을 기록해둡니다.
URL : /html/2022/11/03/html5-style.html
Description : HTML5 Style에 대한 내용을 기록해둡니다.
Content : z-index 지정 (레이어별 우선순위)

레어별로 표시되는 우선순위를 선택할 수 있다.
순위 설정 속성명은 z-index로 해주면 된다.


z-order : ❌
z-index : ⭕


얼핏보면 z-order인 것 같은데 z-index로 설정해야 한다.

z-index 예제
.memo {
z-index: 10;
}


위와 같이 설정해주면 된다.

opacity (투명 레이어)

레이어를 투명하게 할 수 있다.

.memo {
opacity: 0.5;
}
["z-index 지정 (레이어별 우선순위)\n\n레어별로 표시되는 우선순위를 선택할 수 있다. \n순위 설정 속성명은 z-index로 해주면 된다.\n\n\n z-order : ❌\n z-index : ⭕\n\n\n얼핏보면 z-order인 것 같은데 z-index로 설정해야 한다.\n\nz-index 예제\n.memo {\n z-index: 10;\n}\n\n\n위와 같이 설정해주면 된다.\n\nopacity (투명 레이어)\n\n레이어를 투명하게 할 수 있다.\n\n.memo {\n opacity: 0.5;\n}\n"]
Title : 회사에서 2년만에 희망퇴직 프로그램을 진행한다.
URL : /diary/2022/11/03/%ED%9D%AC%EB%A7%9D%ED%87%B4%EC%A7%81%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8.html
Description : 전체 직원의 40%를 목표로 희망퇴직 프로그램을 진행한다고 한다.
Content : 심란하다.
회사에서 2년만에 희망퇴직 프로그램을 진행한다.
전체 직원의 40%를 감원하는 것이 목표다.

직장 어린이집 때문에 회사 근처로 이사를 왔다.
이사한지 3개월만에 벌어진 일이다.
와이프님도 속상해한다.
이사를 오지 않았으면 마음이 덜 쓰였을 것 같다.

10년 후에 내가 이 글을 보면 어떤 느낌일까?
나는 그때 어디에서 무엇을 하고 있을까?

식사 이력




구분
메뉴
비고




아침
 
 


점심
돼지고기 김치덮밥
 


저녁
돼지고기 구이
 



["심란하다. \n회사에서 2년만에 희망퇴직 프로그램을 진행한다. \n전체 직원의 40%를 감원하는 것이 목표다.\n\n직장 어린이집 때문에 회사 근처로 이사를 왔다. \n이사한지 3개월만에 벌어진 일이다. \n와이프님도 속상해한다. \n이사를 오지 않았으면 마음이 덜 쓰였을 것 같다.\n\n10년 후에 내가 이 글을 보면 어떤 느낌일까? \n나는 그때 어디에서 무엇을 하고 있을까?\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n  \n  \n \n \n 점심\n 돼지고기 김치덮밥\n  \n \n \n 저녁\n 돼지고기 구이\n  \n \n \n\n"]
Title : GitHub Pages 포스트 읽는데 걸리는 시간 표시하는 방법
URL : /github-pages/2022/11/02/jekyll-calculating-time-to-read-for-a-post.html
Description : 깃허브 페이지에서 단어수를 체크해서 글을 읽는데 필요한 예상 시간 계산 방법
Content : 요즘 잘 작성된 글들은 글을 읽는데 걸리는 예상 시간을 같이 표기하곤 한다.
처음에는 이것이 실제 사용자가 글을 읽는데 걸리는 시간을 측정한 통계 데이터이줄 알았다.
오늘 우연한 기회로 이것이 어떻게 구현되었는지 알게 되었는데 생각보다 간단하게 구현되어 있었다.

글을 읽는데 소요되는 시간 예상 방법

GitHub Pages로 작성된 포스트를 읽는데 걸리는 시간을 계산하는 공식은 아래와 같다.


글을 읽는데 걸리는 시간 = 단어수 / 5단어 / 60초


1초에 5단어씩 읽는다고 가정하면 1초동안 5단어를 읽을 수 있다.
1분은 60초이므로 1분에 300단어를 읽을 수 있다.
즉, 단어수를 300으로 나누면 그 글을 읽는데 걸리는 시간을 계산할 수 있다.

예제


{% capture count_words %}{{ page.content | number_of_words }}{% endcapture %}
{% capture time_words %}{{ count_words | divided_by: 5 }}{% endcapture %}
- 단어수 : {{ count_words }}
- 읽는데 걸리는 시간 : ~ {{ time_words | divided_by: 60 }} 분



결과


단어수 : 185
읽는데 걸리는 시간 : ~ 0 분

["요즘 잘 작성된 글들은 글을 읽는데 걸리는 예상 시간을 같이 표기하곤 한다. \n처음에는 이것이 실제 사용자가 글을 읽는데 걸리는 시간을 측정한 통계 데이터이줄 알았다. \n오늘 우연한 기회로 이것이 어떻게 구현되었는지 알게 되었는데 생각보다 간단하게 구현되어 있었다.\n\n글을 읽는데 소요되는 시간 예상 방법\n\nGitHub Pages로 작성된 포스트를 읽는데 걸리는 시간을 계산하는 공식은 아래와 같다.\n\n\n 글을 읽는데 걸리는 시간 = 단어수 / 5단어 / 60초\n\n\n1초에 5단어씩 읽는다고 가정하면 1초동안 5단어를 읽을 수 있다. \n1분은 60초이므로 1분에 300단어를 읽을 수 있다. \n즉, 단어수를 300으로 나누면 그 글을 읽는데 걸리는 시간을 계산할 수 있다.\n\n예제\n\n\n{% capture count_words %}{{ page.content | number_of_words }}{% endcapture %}\n{% capture time_words %}{{ count_words | divided_by: 5 }}{% endcapture %}\n- 단어수 : {{ count_words }}\n- 읽는데 걸리는 시간 : ~ {{ time_words | divided_by: 60 }} 분\n\n\n\n결과\n\n\n 단어수 : 185\n 읽는데 걸리는 시간 : ~ 0 분\n\n"]
Title : 내 문장이 그렇게 이상한가요? 퇴고를 위한 책 구입
URL : /diary/2022/11/02/%EB%82%B4%EB%AC%B8%EC%9E%A5%EC%9D%B4%EA%B7%B8%EB%A0%87%EA%B2%8C%EC%9D%B4%EC%83%81%ED%95%9C%EA%B0%80%EC%9A%94.html
Description : 2022년 11월 2일 정말 오랜만에 책을 구입했다.
Content : 개인적인 업무


작은도서관 책 분실 확인 (조지 아저씨네 정원)
알뜰요금제 가입
문화체육비 신청 (굿모닝쌤 원어민 영어회화)
이발
교통카드 환급


책 구입

내가 드디어 책을 샀다.
내 문장이 그렇게 이상한가요?라는 책으로 쓴 글을 퇴고하는 방법에 대한 책이다.
평소 사고 싶었던 책이다.
김서령 작가님으로부터 글쓰기 교육을 받을 때 추천해주신 책이다.
회사에서 제공하는 복지포인트가 남아서 구입했다.

이발

수원을 다녀왔다.

이발 비용 3만원
염색 비용 1만원
퍼머 비용 3만원 (선결제)


로카모 입금의 정체?

갑자기 로카모라는 곳에서 내 계좌로 14,740원에 입금이 되었다.
로카모가 뭔지 궁금했다.
교통카드 환불을 신청하면 로카모라는 이름으로 입금이 되나보다.

유심을 변경할 예정이라 교통카드 잔액을 환불받았다.
몇 년 전에 베트남 여행중에 한국 유심을 잃어버렸다가 재발급했던 적이 있다.
그 때 기존 교통카드 잔액이 모두 없어져서 속상했던 적이 있다.
이번에는 유심을 미리 환불을 받았다.

식사 이력




구분
메뉴
비고




아침
아보카도
 


점심
돈까스 카레 우동
 


저녁
생굴, 굴전
 



["개인적인 업무\n\n\n 작은도서관 책 분실 확인 (조지 아저씨네 정원)\n 알뜰요금제 가입\n 문화체육비 신청 (굿모닝쌤 원어민 영어회화)\n 이발\n 교통카드 환급\n\n\n책 구입\n\n내가 드디어 책을 샀다. \n내 문장이 그렇게 이상한가요?라는 책으로 쓴 글을 퇴고하는 방법에 대한 책이다. \n평소 사고 싶었던 책이다. \n김서령 작가님으로부터 글쓰기 교육을 받을 때 추천해주신 책이다. \n회사에서 제공하는 복지포인트가 남아서 구입했다.\n\n이발\n\n수원을 다녀왔다.\n\n 이발 비용 3만원\n 염색 비용 1만원\n 퍼머 비용 3만원 (선결제)\n\n\n로카모 입금의 정체?\n\n갑자기 로카모라는 곳에서 내 계좌로 14,740원에 입금이 되었다. \n로카모가 뭔지 궁금했다. \n교통카드 환불을 신청하면 로카모라는 이름으로 입금이 되나보다.\n\n유심을 변경할 예정이라 교통카드 잔액을 환불받았다. \n몇 년 전에 베트남 여행중에 한국 유심을 잃어버렸다가 재발급했던 적이 있다. \n그 때 기존 교통카드 잔액이 모두 없어져서 속상했던 적이 있다. \n이번에는 유심을 미리 환불을 받았다.\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 아보카도\n  \n \n \n 점심\n 돈까스 카레 우동\n  \n \n \n 저녁\n 생굴, 굴전\n  \n \n \n\n"]
Title : GitHub Pages로 작성한 특정 포스트가 누락되어 발행되는 이유
URL : /github-pages/2022/11/01/why-my-post-is-not-deploied.html
Description : 깃허브 페이지로 작성한 글이 디플로이 되지 못하는 경우 해결 방법
Content : GitHub Pages에서 포스트를 작성하는 기본 규칙은 아래와 같습니다.

_/posts 디렉토리에 포스트를 작성해야 함.
파일명은 YYYY-MM-DD로 시작해야 함.
확장자를 md 파일이어야 함.


위와 같은 규칙으로 포스트를 작성하더라도 누락되어 발생되는 경우가 있습니다.
본 페이지는 포스트가 누락되는 여러 원인들을 살펴보고 해결 방법을 설명합니다.

포스트가 누락되어 발행되는 케이스는 아래와 같습니다.

미래의 날짜로 포스팅을 올렸을 경우
오늘 날짜이지만 오전 9시 이전일 경우 (시차 문제)


미래의 날짜로 포스팅을 올렸을 경우

오늘 날짜가 2022년 11월 1일인데, 2022년 11월 2일로 파일을 작성해서 발행하면
해당 포스트는 발행에서 자동으로 누락됩니다.
이는 Jekyll에서 의도한 기능입니다.

빌드 로그를 살펴보면 아래와 같이 의도적으로 해당 포스트를 skip 했다는 것을 알 수 있습니다.


Skipping: _posts/bash/2022-11-02-md has a fure date


이 때는 날짜를 오늘 날짜로 수정하거나, 추후에 다시 빌드하면 됩니다.

오늘 날짜이지만 오전 9시 이전일 경우 (시차 문제)

오늘 날짜의 포스팅이라고 하더라도 발행이 누락될 수 있습니다.
Jekyll에서 포스트의 날짜를 체크하는 기능은 KST 기준이 아니라 UDT 기준입니다.
서울 시간으로 오늘 날짜라고 하더라도, UDT 기준으로는 어제일 수 있기 때문에
UDT 날짜가 변경되는 오전 9시 이전에는 오늘 날짜의 포스트라고 하더라도 누락될 수 있습니다.

_posts 이외의 디렉토리를 빌드하려면?

_posts 이외의 디렉토리를 빌드하려면 _config.yml 파일에 해당 경로를 추가해주면 됩니다.
만약 _pages 디렉토리에 포함된 콘텐츠들도 발행에 포함하고 싶다면 설정 파일에 아래와 같이 추가해주면 됩니다.

include:
- _pages


위와 같이 입력하면 빌드시에 _pages 디렉토리에 포함되 콘텐츠들도 발행에 포함됩니다.
["GitHub Pages에서 포스트를 작성하는 기본 규칙은 아래와 같습니다.\n\n _/posts 디렉토리에 포스트를 작성해야 함.\n 파일명은 YYYY-MM-DD로 시작해야 함.\n 확장자를 md 파일이어야 함.\n\n\n위와 같은 규칙으로 포스트를 작성하더라도 누락되어 발생되는 경우가 있습니다. \n본 페이지는 포스트가 누락되는 여러 원인들을 살펴보고 해결 방법을 설명합니다.\n\n포스트가 누락되어 발행되는 케이스는 아래와 같습니다.\n\n 미래의 날짜로 포스팅을 올렸을 경우\n 오늘 날짜이지만 오전 9시 이전일 경우 (시차 문제)\n\n\n미래의 날짜로 포스팅을 올렸을 경우\n\n오늘 날짜가 2022년 11월 1일인데, 2022년 11월 2일로 파일을 작성해서 발행하면 \n해당 포스트는 발행에서 자동으로 누락됩니다. \n이는 Jekyll에서 의도한 기능입니다.\n\n빌드 로그를 살펴보면 아래와 같이 의도적으로 해당 포스트를 skip 했다는 것을 알 수 있습니다.\n\n\n Skipping: _posts/bash/2022-11-02-md has a fure date\n\n\n이 때는 날짜를 오늘 날짜로 수정하거나, 추후에 다시 빌드하면 됩니다.\n\n오늘 날짜이지만 오전 9시 이전일 경우 (시차 문제)\n\n오늘 날짜의 포스팅이라고 하더라도 발행이 누락될 수 있습니다.\nJekyll에서 포스트의 날짜를 체크하는 기능은 KST 기준이 아니라 UDT 기준입니다. \n서울 시간으로 오늘 날짜라고 하더라도, UDT 기준으로는 어제일 수 있기 때문에 \nUDT 날짜가 변경되는 오전 9시 이전에는 오늘 날짜의 포스트라고 하더라도 누락될 수 있습니다.\n\n_posts 이외의 디렉토리를 빌드하려면?\n\n_posts 이외의 디렉토리를 빌드하려면 _config.yml 파일에 해당 경로를 추가해주면 됩니다. \n만약 _pages 디렉토리에 포함된 콘텐츠들도 발행에 포함하고 싶다면 설정 파일에 아래와 같이 추가해주면 됩니다.\n\ninclude:\n - _pages\n\n\n위와 같이 입력하면 빌드시에 _pages 디렉토리에 포함되 콘텐츠들도 발행에 포함됩니다.\n"]
Title : 같은 어린이집을 다니고 있는 연우네에서 놀러왔다. (가마솥 전통 백암 순대 포장)
URL : /diary/2022/11/01/%EC%97%B0%EC%9A%B0%EB%84%A4.html
Description : 아파트 단지 이웃이면서도 첫째 아들 친구네를 우리집에 초대했다. 만족스러웠던 포장 순대!
Content : 엉망인 것 같았지만 즐거웠던 하루였다.

개인적인 업무


작은도서관 책 분실 확인 (조지 아저씨네 정원)
알뜰요금제 가입
책 배송 확인 (내 문장이 그렇게 이상한가요?)
영어 수업 결제


연우네 방문

같은 아파트 단지에 살면서 같은 어린이집에 아이를 보내는 직장 동료와 친해졌다.
비슷한 점이 너무 많아서 깜짝 놀랐다.
앞으로 자주 만나서 어울리면 좋을 것 같다.


같은 아파트 단지 이웃
같은 직장
같은 어린이집
술 좋아하심


가마솥전통백암순대

와이프님이 정말 가보고 싶어했던 순대집이 있다.
성남 단대오거리역 근처에 있는 가마솥전통백암순대라는 곳이다.
지난 일요일에 방문했을 때는 문이 닫혀있어서 맛을 못 봤다.
오늘 연우네와 함께 먹어보려고 했는데 자리도 없고 내부도 좁아서 포장을 해왔다.


결과는 대만족! 다음번에도 또 포장해오기로 했다!







가마솥전통백암순대 · 경기도 성남시 중원구 중앙동 산성대로350번길 7
★★★★☆ · 한식당









식사 이력




구분
메뉴
비고




아침
 
 


점심
짬뽕밥
사내 식당


저녁
순대 + 뿌링클 순살
가마솥 전통 백암 순대



["엉망인 것 같았지만 즐거웠던 하루였다.\n\n개인적인 업무\n\n\n 작은도서관 책 분실 확인 (조지 아저씨네 정원)\n 알뜰요금제 가입\n 책 배송 확인 (내 문장이 그렇게 이상한가요?)\n 영어 수업 결제\n\n\n연우네 방문\n\n같은 아파트 단지에 살면서 같은 어린이집에 아이를 보내는 직장 동료와 친해졌다. \n비슷한 점이 너무 많아서 깜짝 놀랐다. \n앞으로 자주 만나서 어울리면 좋을 것 같다.\n\n\n 같은 아파트 단지 이웃\n 같은 직장\n 같은 어린이집\n 술 좋아하심\n\n\n가마솥전통백암순대\n\n와이프님이 정말 가보고 싶어했던 순대집이 있다. \n성남 단대오거리역 근처에 있는 가마솥전통백암순대라는 곳이다. \n지난 일요일에 방문했을 때는 문이 닫혀있어서 맛을 못 봤다. \n오늘 연우네와 함께 먹어보려고 했는데 자리도 없고 내부도 좁아서 포장을 해왔다.\n\n\n 결과는 대만족! 다음번에도 또 포장해오기로 했다!\n\n\n\n\n\n \n \n 가마솥전통백암순대 · 경기도 성남시 중원구 중앙동 산성대로350번길 7\n ★★★★☆ · 한식당\n \n \n \n \n \n \n\n\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n  \n  \n \n \n 점심\n 짬뽕밥\n 사내 식당\n \n \n 저녁\n 순대 + 뿌링클 순살\n 가마솥 전통 백암 순대\n \n \n\n"]
Title : 배쉬 쉘에서 echo 명령으로 개행 출력 방법
URL : /bash/2022/11/01/%EB%B0%B0%EC%89%AC-%EA%B0%9C%ED%96%89-%EC%B6%9C%EB%A0%A5-%EB%B0%A9%EB%B2%95.html
Description : Bash Shell에서 개행이 포함된 문자열을 출력하면 개행이 제대로 추력되지 않는다.
Content : 개행 출력 안되는 이슈

output="Hello!\nI am boyinblue"
echo "${output}"


위의 배쉬 쉘 스크립트를 실행해보면 원하는대로 출력이 되지 않는다.

이걸 의도했다.

Hello!
I am boyinblue


실제로는 이렇게 출력된다.

Hello!\nI am boyinblue


개행이 전혀 먹히지 않고 바이패스(bypass)된 상태로 출력된다.

개행을 출력하기 위한 -e 옵션

output="Hello!\nI am boyinblue"
echo -e "${output}"


위와 같이 -e 옵션을 붙여주면 문자열에 포함된 개행 문자를 출력에 표시한다.

Hello!
I am boyinblue


echo 명령 매뉴얼 확인

man echo 명령으로 echo 명령의 매뉴얼을 확인해보면,
-e 옵션을 주면 백슬러쉬를 이스케이프 한다고 되어 있다.


-e enable interpretation of backslash escapes


즉, 개행 문자 외에도 백슬러쉬로 표현하는 모든 문자들을 처리한다.

이상입니다.
["개행 출력 안되는 이슈\n\noutput=\"Hello!", "I am boyinblue\"\necho \"${output}\"\n\n\n위의 배쉬 쉘 스크립트를 실행해보면 원하는대로 출력이 되지 않는다.\n\n이걸 의도했다.\n\nHello!\nI am boyinblue\n\n\n실제로는 이렇게 출력된다.\n\nHello!", "I am boyinblue\n\n\n개행이 전혀 먹히지 않고 바이패스(bypass)된 상태로 출력된다.\n\n개행을 출력하기 위한 -e 옵션\n\noutput=\"Hello!", "I am boyinblue\"\necho -e \"${output}\"\n\n\n위와 같이 -e 옵션을 붙여주면 문자열에 포함된 개행 문자를 출력에 표시한다.\n\nHello!\nI am boyinblue\n\n\necho 명령 매뉴얼 확인\n\nman echo 명령으로 echo 명령의 매뉴얼을 확인해보면, \n-e 옵션을 주면 백슬러쉬를 이스케이프 한다고 되어 있다.\n\n\n -e enable interpretation of backslash escapes\n\n\n즉, 개행 문자 외에도 백슬러쉬로 표현하는 모든 문자들을 처리한다.\n\n이상입니다.\n"]
Title : 유튜브 비디오 무료로 다운로드 받는 방법
URL : /firefox/2022/10/31/how-to-download-youtube-video.html
Description : Firefox add-ons를 이용해서 Youtube Video를 Download 하는 방법을 설명
Content : 유튜브 프리미엄 서비스를 이용하면 유튜브 콘텐츠를 미리 다운로드 받아두었다가 원하는 시점에 재생할 수 있습니다.
파이어폭스 웹브라우저와 부가 기능을 이용하면 무료로 유튜브 콘텐츠를 다운로드 할 수 있습니다.

요약


파이어폭스 웹브라우저 설치
Easy Youtube Video Downloader Express 확장 기능 설치
유튜브 콘텐츠를 무료로 제한없이 다운로드


왜 Easy Youtube Video Downloader Express인가?

파이어폭스 웹브라우저에는 유튜브 비디오를 다운로드 할 수 있는 다양한 애드온즈가 있습니다.
그 중에는 불필요하게 많은 권한을 요구하는 애드온즈도 다수 존재합니다.
Easy Youtube Video Downloader Express는 아래와 같은 장점이 있습니다.


이미 60만명이 이용하고 있는 부가 기능이라 신뢰할 수 있음.
2가지 권한만 요구함.


상세 설명

1. 파이어폭스 웹브라우저를 설치하고 실행합니다.

아래 경로로 접속해서 파이어폭스 웹브라우저를 설치합니다.






Firefox 최신 버전 다운로드
빠른 페이지 로딩, 작은 메모리 사용 및 다양한 기능을 갖춘 새로운 Firefox가 여기 있습니다.









2. 애플리케이션 메뉴열기 - 부가 기능 및 테마



웹브라우저 오른쪽 상단에 있는 애플리케이션 메뉴열기 버튼을 클릭하고,
부가 기능 및 테마 메뉴를 선택합니다.

3. 더 많은 부가 기능 찾기에서 검색



더 많은 부가 기능 찾기에서 Easy Youtube Video Downloader Express를 검색합니다.

4. 부가기능 프로그램 이름과 제작자 이름을 확인



프로그램 이름이 Easy Youtube Video Downloader Express인지 확인하고,
제작자가 Dishita인 것도 확인합니다.


다른 애드온들은 과도하게 많은 권한을 요구하는 경우가 많기 때문에 꼭 이걸 설치하시기 바랍니다.


5. 필요한 권한을 체크합니다.



Easy Youtube Video Downloader Express는 2가지 권한만 필요합니다.


파일을 다운로드하고 브라우저의 다운로드 기록을 읽고 수정
모든 웹사이트에서 사용자의 데이터에 접근


6. Firefox에 추가 버튼을 눌러 설치



Firefox에 추가 버튼을 눌러서 애드온을 설치합니다.

7. 추가 버튼을 선택



어떤 권한이 필요한지를 한 번 더 체크하는 절차가 진행됩니다.
추가 버튼을 눌러서 설치를 계속합니다.

8. 설치 완료



설치가 모두 완료되었습니다.

9. 다운로드 실행



다운로드를 원하는 영상을 선택한 후, 내려받기 버튼을 클릭합니다.
어떤 화질로 다운로드 할 것인지를 선택하면 잠시 후 다운로드가 완료됩니다.

결론

파이어폭스의 Easy Youtube Video Downloader Express 부가 기능을 사용하면
유튜브 비디오를 무료로 제한없이 다운로드 할 수 있습니다.
["유튜브 프리미엄 서비스를 이용하면 유튜브 콘텐츠를 미리 다운로드 받아두었다가 원하는 시점에 재생할 수 있습니다. \n파이어폭스 웹브라우저와 부가 기능을 이용하면 무료로 유튜브 콘텐츠를 다운로드 할 수 있습니다.\n\n요약\n\n\n 파이어폭스 웹브라우저 설치\n Easy Youtube Video Downloader Express 확장 기능 설치\n 유튜브 콘텐츠를 무료로 제한없이 다운로드\n\n\n왜 Easy Youtube Video Downloader Express인가?\n\n파이어폭스 웹브라우저에는 유튜브 비디오를 다운로드 할 수 있는 다양한 애드온즈가 있습니다. \n그 중에는 불필요하게 많은 권한을 요구하는 애드온즈도 다수 존재합니다. \nEasy Youtube Video Downloader Express는 아래와 같은 장점이 있습니다.\n\n\n 이미 60만명이 이용하고 있는 부가 기능이라 신뢰할 수 있음.\n 2가지 권한만 요구함.\n\n\n상세 설명\n\n1. 파이어폭스 웹브라우저를 설치하고 실행합니다.\n\n아래 경로로 접속해서 파이어폭스 웹브라우저를 설치합니다.\n\n\n\n\n \n \n Firefox 최신 버전 다운로드\n 빠른 페이지 로딩, 작은 메모리 사용 및 다양한 기능을 갖춘 새로운 Firefox가 여기 있습니다.\n \n \n \n \n \n \n\n\n\n2. 애플리케이션 메뉴열기 - 부가 기능 및 테마\n\n\n\n웹브라우저 오른쪽 상단에 있는 애플리케이션 메뉴열기 버튼을 클릭하고, \n부가 기능 및 테마 메뉴를 선택합니다.\n\n3. 더 많은 부가 기능 찾기에서 검색\n\n\n\n더 많은 부가 기능 찾기에서 Easy Youtube Video Downloader Express를 검색합니다.\n\n4. 부가기능 프로그램 이름과 제작자 이름을 확인\n\n\n\n프로그램 이름이 Easy Youtube Video Downloader Express인지 확인하고, \n제작자가 Dishita인 것도 확인합니다.\n\n\n 다른 애드온들은 과도하게 많은 권한을 요구하는 경우가 많기 때문에 꼭 이걸 설치하시기 바랍니다.\n\n\n5. 필요한 권한을 체크합니다.\n\n\n\nEasy Youtube Video Downloader Express는 2가지 권한만 필요합니다.\n\n\n 파일을 다운로드하고 브라우저의 다운로드 기록을 읽고 수정\n 모든 웹사이트에서 사용자의 데이터에 접근\n\n\n6. Firefox에 추가 버튼을 눌러 설치\n\n\n\nFirefox에 추가 버튼을 눌러서 애드온을 설치합니다.\n\n7. 추가 버튼을 선택\n\n\n\n어떤 권한이 필요한지를 한 번 더 체크하는 절차가 진행됩니다. \n추가 버튼을 눌러서 설치를 계속합니다.\n\n8. 설치 완료\n\n\n\n설치가 모두 완료되었습니다.\n\n9. 다운로드 실행\n\n\n\n다운로드를 원하는 영상을 선택한 후, 내려받기 버튼을 클릭합니다. \n어떤 화질로 다운로드 할 것인지를 선택하면 잠시 후 다운로드가 완료됩니다.\n\n결론\n\n파이어폭스의 Easy Youtube Video Downloader Express 부가 기능을 사용하면 \n유튜브 비디오를 무료로 제한없이 다운로드 할 수 있습니다.\n"]
Title : 유플러스 알뜰 요금제로 변경하기 위해서 노력중이다.
URL : /diary/2022/10/31/%EC%9C%A0%ED%94%8C%EB%9F%AC%EC%8A%A4-%EC%95%8C%EB%9C%B0%EC%9A%94%EA%B8%88%EC%A0%9C-%EA%B0%80%EC%9E%85-%EC%A7%84%ED%96%89%EC%A4%91.html
Description : 기존에 사용하던 유플러스 약정 기간이 종료되어 알뜰 요금제로 변경을 시도하고 있습니다.
Content : 시제가 현재 진행형인 이유는, 아직 알뜰 요금제 가입이 완료되지 않아서다.
알뜰 요금제 유심을 구입하기는 했지만, 아직 개통을 완료하지는 못했기 때문이다.
LG Uplus를 사용하다가 알뜰 요금제를 사용하려고 하니, 상담사와 통화를 하는 것부터가 쉽지 않았다.
같은 통신망을 사용한다고 하더라도 CS나 멤버십 부분에서 제법 차이가 나는 것 같다.
싼데는 다 이유가 있고, 싼 맛에 갈아탄다는 마인드셋으로 접근하고 있다.

오늘 있었던 일


✅ 유플러스 알뜰 요금제용 유심 구입
✅ 회사 복지 포인트 사용 완료
✅ 커피 인류에서 티타임
✅ 회사 피트니스 이용 (트레드밀 30분)
✅ 둘째 아들의 회사 어린이집 입학 확정


유플러스 알뜰 요금제용 갈아타는 중

약 2주 전에 유플러스 약정이 종료되었다.
와이프님의 권유로 알뜰 요금제를 써보기로 마음 먹었다.
말이 권유지 실제로는 강권에 가깝다고 본다
가장 먼저 할 일은 유심을 구입하는 것이다.

알뜰 요금제용 유심 구입


인터넷으로 유심을 구입했다.
택배로 오는게 아니라 근처 편의점에서 직접 수령할 수 있어서 좋다.
사무실 근처에 있는 `이마트24 고등현대센터점’에 방문했다.

무인 편의점이라서 직원이 없었다.
알뜰 유심은 어디에 있는거지?
다행히 매대에서 원하는 상품을 찾는 것은 어렵지 않았다.

하지만 셀프 계산대에서 쿠폰을 어떻게 결제해야 되는지는 어려웠다.
결국 이마트24 상담원과 통화해서 결제를 할 수 있었다.


이마트24 상담번호 : 02-6916-1500


알뜰 요금제 개통(진행중)


우여곡절 끝에 유심을 손에 넣었다.
다음 단계는 개통이다.
이것 역시도 쉽지 않다.
여러번 시도를 해봤지만 계속 실패했다.


유플러스 알뜰요금제 개통 상담번호 : 1670-0283


개통을 위한 상담 전화번호는 연결이 불가능했다.
3번 전화를 해봤는데 3번 모두 부재중 이라는 메시지를 토해내고 통화가 끊겼다.

챗봇을 통해서 SOS를 신청했다.
내일 상담사가 연락할 예정이라고 한다.
AS 기사가 방문하는 것도 아니고, 상담 전화가 내일 가능하다는 것이 놀라울 따름이다.
알뜰 요금제가 저렴한 이유 중의 하나가 이것인가 보다.


저렴하게 쓰기 위해서는 아닥하고 불편함을 감수해야 한다.


가입을 원하는 요금제

무제한 요금제가 9,900원 밖에 안 한다고 해서 써보기로 했다.
데이터는 1GB 밖에 없지만, 소진하면 1Mbps의 속도로 무제한 사용이 가능하다.


요금 : 월 9,900원
전화/SMS : 무제한
데이터 통화 : 1GB (소진시 1mbps로 무제한 이용 가능)


아주 매력적인 요금제다.
저 요금에 저 정도 혜택이라면 이런 사소한 불편함 따위는 얼마든지 참을 수 있다.

회사 복지포인트 사용 완료

이해가 안 된다.
사용 기한이 빠른 복지포인트가 먼저 차감이 되어야 하는게 상식 아닌가?
우리 회사 복지몰에서는 사용 기한이 더 많이 남은 포인트부터 먼저 차감된다.

아무튼 오늘까지 모두 소진해야 하는 회사 복지 포인트로 오랜만에 책을 구입했다.
내 문장이 그렇게 이상한가요?라는 책으로 김지영 작가님께서 추천해주신 책이다.
나의 글쓰기에 도움이 되면 좋겠다.
어서 책이 왔으면 좋겠다.

커피 인류



요즘 팀원분들과 거의 매일 티타임을 가지고 있다.
고등동은 고등동 카페거리라고 불러도 될 정도로 카페가 많다.
마치 도장깨기 하는 것처럼 여러 카페를 가보는 중이다.
오늘 방문한 카페는 커피 인류라는 카페다.
인테리어도 음료도 만족스러운 곳이었다.



내부 인테리어는 깔끔하고 예쁘다.
넓직한 공간이라서 편하게 앉아서 커피와 담소를 즐길 수 있다.



먹지는 않지만 디저트도 찍어봤다.

성남사랑상품권(chak) 사용 가능하다.




역류성 식도염 때문에 커피 대신 루이보스티를 마셔야 했다.
루이보스티는 영어로 Rooibos tea다.
멍청한 파파고는 Louis Vosty로 번역 결과를 토해냈다.
내가 파파고의 멍청한 번역을 수정해줬다.


Louis Vosty ❌
Rooibos tea ⭕


트레드밀 30분


회사 휘트니스에서 트레드밀을 30분간 이용했다.
30분간 열심히 운동했는데 칼로리 소모량이 326kcal에 불과했다.


런닝 머신 (running machine) ❌
트레드밀 (threadmill) ⭕


런닝 머신은 콩글리쉬이다. 정확한 영어 표현은 threadmill(트레드밀)이다.

둘째 아들 사내 어린이집 입학 확정

둘째 아들도 내년부터 회사 어린이집을 갈 수 있다.
9명 모집에 3명 지원이니 당연한 결과인 것 같다.

오늘 식사 이력

큰일이다. 내가 무엇을 먹었는지 잘 기억하지 못한다.
특히 회사에서 먹은 점심밥이 무엇이었는지 기억이 안 난다.
치매를 예방하는 차원에서 최대한 기억을 떠올려서 작성해 보자!




구분
메뉴
비고




아침
핫도그 1개 + 아보카도 1개
 


점심
돈육 김치찌개?
아마도?


저녁
김치찌개 + 아들이 먹다 남은 밥
 




["시제가 현재 진행형인 이유는, 아직 알뜰 요금제 가입이 완료되지 않아서다. \n알뜰 요금제 유심을 구입하기는 했지만, 아직 개통을 완료하지는 못했기 때문이다. \nLG Uplus를 사용하다가 알뜰 요금제를 사용하려고 하니, 상담사와 통화를 하는 것부터가 쉽지 않았다. \n같은 통신망을 사용한다고 하더라도 CS나 멤버십 부분에서 제법 차이가 나는 것 같다. \n싼데는 다 이유가 있고, 싼 맛에 갈아탄다는 마인드셋으로 접근하고 있다.\n\n오늘 있었던 일\n\n\n ✅ 유플러스 알뜰 요금제용 유심 구입\n ✅ 회사 복지 포인트 사용 완료\n ✅ 커피 인류에서 티타임\n ✅ 회사 피트니스 이용 (트레드밀 30분)\n ✅ 둘째 아들의 회사 어린이집 입학 확정\n\n\n유플러스 알뜰 요금제용 갈아타는 중\n\n약 2주 전에 유플러스 약정이 종료되었다. \n와이프님의 권유로 알뜰 요금제를 써보기로 마음 먹었다. \n말이 권유지 실제로는 강권에 가깝다고 본다 \n가장 먼저 할 일은 유심을 구입하는 것이다.\n\n알뜰 요금제용 유심 구입\n\n\n인터넷으로 유심을 구입했다. \n택배로 오는게 아니라 근처 편의점에서 직접 수령할 수 있어서 좋다. \n사무실 근처에 있는 `이마트24 고등현대센터점’에 방문했다.\n\n무인 편의점이라서 직원이 없었다. \n알뜰 유심은 어디에 있는거지? \n다행히 매대에서 원하는 상품을 찾는 것은 어렵지 않았다.\n\n하지만 셀프 계산대에서 쿠폰을 어떻게 결제해야 되는지는 어려웠다. \n결국 이마트24 상담원과 통화해서 결제를 할 수 있었다.\n\n\n 이마트24 상담번호 : 02-6916-1500\n\n\n알뜰 요금제 개통(진행중)\n\n\n우여곡절 끝에 유심을 손에 넣었다. \n다음 단계는 개통이다. \n이것 역시도 쉽지 않다. \n여러번 시도를 해봤지만 계속 실패했다.\n\n\n 유플러스 알뜰요금제 개통 상담번호 : 1670-0283\n\n\n개통을 위한 상담 전화번호는 연결이 불가능했다. \n3번 전화를 해봤는데 3번 모두 부재중 이라는 메시지를 토해내고 통화가 끊겼다.\n\n챗봇을 통해서 SOS를 신청했다. \n내일 상담사가 연락할 예정이라고 한다. \nAS 기사가 방문하는 것도 아니고, 상담 전화가 내일 가능하다는 것이 놀라울 따름이다. \n알뜰 요금제가 저렴한 이유 중의 하나가 이것인가 보다.\n\n\n 저렴하게 쓰기 위해서는 아닥하고 불편함을 감수해야 한다.\n\n\n가입을 원하는 요금제\n\n무제한 요금제가 9,900원 밖에 안 한다고 해서 써보기로 했다. \n데이터는 1GB 밖에 없지만, 소진하면 1Mbps의 속도로 무제한 사용이 가능하다.\n\n\n 요금 : 월 9,900원\n 전화/SMS : 무제한\n 데이터 통화 : 1GB (소진시 1mbps로 무제한 이용 가능)\n\n\n아주 매력적인 요금제다. \n저 요금에 저 정도 혜택이라면 이런 사소한 불편함 따위는 얼마든지 참을 수 있다.\n\n회사 복지포인트 사용 완료\n\n이해가 안 된다. \n사용 기한이 빠른 복지포인트가 먼저 차감이 되어야 하는게 상식 아닌가? \n우리 회사 복지몰에서는 사용 기한이 더 많이 남은 포인트부터 먼저 차감된다.\n\n아무튼 오늘까지 모두 소진해야 하는 회사 복지 포인트로 오랜만에 책을 구입했다. \n내 문장이 그렇게 이상한가요?라는 책으로 김지영 작가님께서 추천해주신 책이다. \n나의 글쓰기에 도움이 되면 좋겠다. \n어서 책이 왔으면 좋겠다.\n\n커피 인류\n\n\n\n요즘 팀원분들과 거의 매일 티타임을 가지고 있다. \n고등동은 고등동 카페거리라고 불러도 될 정도로 카페가 많다. \n마치 도장깨기 하는 것처럼 여러 카페를 가보는 중이다. \n오늘 방문한 카페는 커피 인류라는 카페다. \n인테리어도 음료도 만족스러운 곳이었다.\n\n\n\n내부 인테리어는 깔끔하고 예쁘다. \n넓직한 공간이라서 편하게 앉아서 커피와 담소를 즐길 수 있다.\n\n\n\n먹지는 않지만 디저트도 찍어봤다.\n\n 성남사랑상품권(chak) 사용 가능하다.\n\n\n\n\n역류성 식도염 때문에 커피 대신 루이보스티를 마셔야 했다. \n루이보스티는 영어로 Rooibos tea다. \n멍청한 파파고는 Louis Vosty로 번역 결과를 토해냈다. \n내가 파파고의 멍청한 번역을 수정해줬다.\n\n\n Louis Vosty ❌\n Rooibos tea ⭕\n\n\n트레드밀 30분\n\n\n회사 휘트니스에서 트레드밀을 30분간 이용했다. \n30분간 열심히 운동했는데 칼로리 소모량이 326kcal에 불과했다.\n\n\n 런닝 머신 (running machine) ❌\n 트레드밀 (threadmill) ⭕\n\n\n런닝 머신은 콩글리쉬이다. 정확한 영어 표현은 threadmill(트레드밀)이다.\n\n둘째 아들 사내 어린이집 입학 확정\n\n둘째 아들도 내년부터 회사 어린이집을 갈 수 있다. \n9명 모집에 3명 지원이니 당연한 결과인 것 같다.\n\n오늘 식사 이력\n\n큰일이다. 내가 무엇을 먹었는지 잘 기억하지 못한다. \n특히 회사에서 먹은 점심밥이 무엇이었는지 기억이 안 난다. \n치매를 예방하는 차원에서 최대한 기억을 떠올려서 작성해 보자!\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 핫도그 1개 + 아보카도 1개\n  \n \n \n 점심\n 돈육 김치찌개?\n 아마도?\n \n \n 저녁\n 김치찌개 + 아들이 먹다 남은 밥\n  \n \n \n\n\n"]
Title : bash에서 라인 단위로 파싱하는 방법 (IFS 구분자 변경)
URL : /bash/2022/10/31/how-to-parse-line-by-line.html
Description : How to parse line by line on Bash
Content : bash 쉘에서 for 구문을 사용하면 공백을 기준으로 구분된다.
간혹 개행을 기준으로 분리해서 처리가 필요할 때가 있다.
IFS 구분자를 변경해서 라인별로 처리하는 방법을 설명한다.

예제

lines=$(curl "https://boyinblue.github.io")

IFS_OLD=$IFS
IFS=$'\n'
for line in ${lines}
do
echo "${line}"
done
IFS=$IFS_OLD


위의 예제를 살펴보면, IFS_OLD에 기존 구분자를 저장한 다음에,
IFS에 $'\n'을 대입한다.
그 다음에 다시 IFS에 $IFS_OLD를 할당한다.
이렇게 하면 기존에 사용하던 구분자 설정으로 다시 돌아갈 수 있어서 편리하다.

주의할 점

lines=$(curl "https://boyinblue.github.io")

IFS_OLD=$IFS
IFS=$'\n'
for line in "${lines}"
do
echo "${line}"
done
IFS=$IFS_OLD


for 구문을 돌릴 문자열을 쌍따옴표로 인용하면
원하는 결과를 얻을 수 없이 ${lines} 변수 전체가
하나의 라인으로 인식되기 때문에 원하는 결과를 얻을 수 없다.

["bash 쉘에서 for 구문을 사용하면 공백을 기준으로 구분된다. \n간혹 개행을 기준으로 분리해서 처리가 필요할 때가 있다. \nIFS 구분자를 변경해서 라인별로 처리하는 방법을 설명한다.\n\n예제\n\nlines=$(curl \"https://boyinblue.github.io\")\n\nIFS_OLD=$IFS\nIFS=$'", "'\nfor line in ${lines}\ndo\n echo \"${line}\"\ndone\nIFS=$IFS_OLD\n\n\n위의 예제를 살펴보면, IFS_OLD에 기존 구분자를 저장한 다음에, \nIFS에 $'", "'을 대입한다. \n그 다음에 다시 IFS에 $IFS_OLD를 할당한다. \n이렇게 하면 기존에 사용하던 구분자 설정으로 다시 돌아갈 수 있어서 편리하다.\n\n주의할 점\n\nlines=$(curl \"https://boyinblue.github.io\")\n\nIFS_OLD=$IFS\nIFS=$'", "'\nfor line in \"${lines}\"\ndo\n echo \"${line}\"\ndone\nIFS=$IFS_OLD\n\n\nfor 구문을 돌릴 문자열을 쌍따옴표로 인용하면 \n원하는 결과를 얻을 수 없이 ${lines} 변수 전체가 \n하나의 라인으로 인식되기 때문에 원하는 결과를 얻을 수 없다.\n\n"]
Title : 파이썬 No module named 에러시 설치해야 할 모듈 정리
URL : /python/2022/10/30/python-no-module-named-error.html
Description : 파이썬 스크립트 실행시 No module named 에러시 설치해야 할 모듈 정리
Content : 문제의 상황

No module named 에러

파이썬 스크립트 실행시에 “No module named”로 표시되는 에러는 필요한 모듈을 찾지 못해서 발생한다.
pip3 명령으로 필요한 모듈을 설치하면 된다.

No module named 'speech_recognition' 에러가 발생하면,
SpeechRecognition 이라는 모듈을 설치해주면 된다.

$ sudo pip3 install SpeechRecognition


에러별 설치해야 하는 모듈 리스트




에러
설치해야 할 모듈
비고




No module named ‘speech_recognition’
sudo pip3 install SpeechRecognition
 


No module named ‘bs4’
sudo pip3 install beautifulsoup4
 


No module named ‘tkinter’
sudo apt-get install python3-tk
 




pip3: 명령이 없습니다 에러 발생할 경우

pip3 install 명령으로 모듈을 설치할 때, pip3: 명령이 없습니다. 발생하면
python3-pip 패키지를 설치하면 된다.

sudo apt-get install python3-pip


["문제의 상황\n\nNo module named 에러\n\n파이썬 스크립트 실행시에 “No module named”로 표시되는 에러는 필요한 모듈을 찾지 못해서 발생한다. \npip3 명령으로 필요한 모듈을 설치하면 된다.\n\nNo module named 'speech_recognition' 에러가 발생하면, \nSpeechRecognition 이라는 모듈을 설치해주면 된다.\n\n$ sudo pip3 install SpeechRecognition\n\n\n에러별 설치해야 하는 모듈 리스트\n\n\n \n \n 에러\n 설치해야 할 모듈\n 비고\n \n \n \n \n No module named ‘speech_recognition’\n sudo pip3 install SpeechRecognition\n  \n \n \n No module named ‘bs4’\n sudo pip3 install beautifulsoup4\n  \n \n \n No module named ‘tkinter’\n sudo apt-get install python3-tk\n  \n \n \n\n\npip3: 명령이 없습니다 에러 발생할 경우\n\npip3 install 명령으로 모듈을 설치할 때, pip3: 명령이 없습니다. 발생하면 \npython3-pip 패키지를 설치하면 된다.\n\nsudo apt-get install python3-pip\n\n\n"]
Title : 희망대공원 산책 및 세이브존에서 옷 구입 (성남시 수정구 신흥동)
URL : /diary/2022/10/30/%ED%9D%AC%EB%A7%9D%EB%8C%80%EA%B3%B5%EC%9B%90.html
Description : 할로윈 데이에 이태원에서 150여명이 압사하는 비극적인 참사가 발생했습니다. 가족들과 집에서 가까운 희망대공원에서 차분한 하루를 보냈습니다.
Content : 2022년 10월 30일 할로윈 데이는 매우 비극적인 날이다.
축제를 즐기기 위한 많은 인파가 이태원에 몰렸고,
150여명이 압사하는 비극적인 재난이 발생했다.
너무 안타까운 일이고, 생각하고 싶지도 않다.

가족들과 조용히 집에서 멀지 않은 공원을 다녀왔다.

✅ 희망대공원 산책
✅ 세이브존에서 와이프님 옷 구입
✅ 버거킹에서 점심 식사


희망대공원 산책



일요일 아침 최초 계획은 남한산성을 가보는 것이었다.
오래전에 ROTC 후보생으로 학생중앙군사학교에서 훈련을 받았다.
그 당시에 행군하면서 올랐던 남한산성에 오랜만에 가보고 싶었다.
남한산성은 집에서 가까운 거리임에도 불구하고,
네비게이션이 1시간이나 걸린다고 했다.
시간이 너무 소요될 것 같아서 목적지를 희망대공원으로 바꿨다.

희망대공원은 누구나 무료로 이용할 수 있는 공원이다.
잘 조성된 공원에서 많은 시민들이 킥보드도 타고, 공놀이도 하고, 담소도 즐기고 있었다.
우리 가족도 희망대공원에서 즐거운 시간을 보냈다.

세이브존에서 와이프님 옷 구입



희망대공원에 주차를 하고 점심 먹으로 가다보니
세이브존에서 옷을 저렴하게 판매하고 있었다.
와이프님께서 정신이 나간 사람처럼 옷을 골랐다.
그 자리에서 총 옷 5벌을 구입했다.




구분
금액
장소
비고




와이프님 옷
89,800원
세이브존
총 5벌




버거킹에서 점심 식사

할인 행사를 진행하는 버거들 위주로 구입을 했다.
첫째 아들이 와퍼 햄버거 하나를 모두 다 먹고,
치즈스틱도 2개나 먹었다고 했다.




구분
단가
수량
금액
비고
 




치즈스틱
1,000원
2개
2,000원
 
 


불고기와퍼
5,500원
2개
 
11,000원
 


콰트로치즈와퍼
4,500원
1개
4,500원
 
 


아메리카노
1,000원
1잔
1,000원
 
 


총 비용
18,500원
 
 
 
 





위의 금액은 확실하지 않다. 카드사에는 15,500원으로 찍혀 있다.


킥보드 가지러 희망대공원 다시 다녀옴



집에 도착해서 우리 아들의 킥보드가 없어졌다는 것을 발견했다.
나 혼자 희망대공원에 가서 킥보드를 찾아왔다.
킥보드를 찾아서 지하주차장으로 내려가는데,
나무 실루엣이 너무 멋져서 사진을 한 장 촬영했다.

잠깐 들어가서 킥보드를 챙겨왔는데 주차비 400원이 발생했다.
잠깐 회차하는데 주차비를 내려고 하니 조금 아쉬웠다.
경유 저공해 자동차는 할인이 안되어서 그것도 아쉬웠다.




구분
금액
비고




희망대공원 주차료
3,200원
첫 번째 주차


희망대공원 주차료
400원
킥보드 찾으러 두 번째 주차




지출




구분
금액
장소
비고




와이프님 옷
89,800원
세이브존
총 5벌


점심식사
15,500원
버거킹
 


주차료
3,600원
희망대공원 주차장
2회




식사 이력




구분
메뉴
비고




아침
짬뽕
 


점심
버거킹
 


저녁
소세지, 쌀밥 등
 




["2022년 10월 30일 할로윈 데이는 매우 비극적인 날이다. \n축제를 즐기기 위한 많은 인파가 이태원에 몰렸고, \n150여명이 압사하는 비극적인 재난이 발생했다. \n너무 안타까운 일이고, 생각하고 싶지도 않다.\n\n가족들과 조용히 집에서 멀지 않은 공원을 다녀왔다.\n\n ✅ 희망대공원 산책\n ✅ 세이브존에서 와이프님 옷 구입\n ✅ 버거킹에서 점심 식사\n\n\n희망대공원 산책\n\n\n\n일요일 아침 최초 계획은 남한산성을 가보는 것이었다. \n오래전에 ROTC 후보생으로 학생중앙군사학교에서 훈련을 받았다. \n그 당시에 행군하면서 올랐던 남한산성에 오랜만에 가보고 싶었다. \n남한산성은 집에서 가까운 거리임에도 불구하고, \n네비게이션이 1시간이나 걸린다고 했다. \n시간이 너무 소요될 것 같아서 목적지를 희망대공원으로 바꿨다.\n\n희망대공원은 누구나 무료로 이용할 수 있는 공원이다. \n잘 조성된 공원에서 많은 시민들이 킥보드도 타고, 공놀이도 하고, 담소도 즐기고 있었다. \n우리 가족도 희망대공원에서 즐거운 시간을 보냈다.\n\n세이브존에서 와이프님 옷 구입\n\n\n\n희망대공원에 주차를 하고 점심 먹으로 가다보니 \n세이브존에서 옷을 저렴하게 판매하고 있었다. \n와이프님께서 정신이 나간 사람처럼 옷을 골랐다. \n그 자리에서 총 옷 5벌을 구입했다.\n\n\n \n \n 구분\n 금액\n 장소\n 비고\n \n \n \n \n 와이프님 옷\n 89,800원\n 세이브존\n 총 5벌\n \n \n\n\n버거킹에서 점심 식사\n\n할인 행사를 진행하는 버거들 위주로 구입을 했다. \n첫째 아들이 와퍼 햄버거 하나를 모두 다 먹고, \n치즈스틱도 2개나 먹었다고 했다.\n\n\n \n \n 구분\n 단가\n 수량\n 금액\n 비고\n  \n \n \n \n \n 치즈스틱\n 1,000원\n 2개\n 2,000원\n  \n  \n \n \n 불고기와퍼\n 5,500원\n 2개\n  \n 11,000원\n  \n \n \n 콰트로치즈와퍼\n 4,500원\n 1개\n 4,500원\n  \n  \n \n \n 아메리카노\n 1,000원\n 1잔\n 1,000원\n  \n  \n \n \n 총 비용\n 18,500원\n  \n  \n  \n  \n \n \n\n\n\n 위의 금액은 확실하지 않다. 카드사에는 15,500원으로 찍혀 있다.\n\n\n킥보드 가지러 희망대공원 다시 다녀옴\n\n\n\n집에 도착해서 우리 아들의 킥보드가 없어졌다는 것을 발견했다. \n나 혼자 희망대공원에 가서 킥보드를 찾아왔다. \n킥보드를 찾아서 지하주차장으로 내려가는데, \n나무 실루엣이 너무 멋져서 사진을 한 장 촬영했다.\n\n잠깐 들어가서 킥보드를 챙겨왔는데 주차비 400원이 발생했다. \n잠깐 회차하는데 주차비를 내려고 하니 조금 아쉬웠다. \n경유 저공해 자동차는 할인이 안되어서 그것도 아쉬웠다.\n\n\n \n \n 구분\n 금액\n 비고\n \n \n \n \n 희망대공원 주차료\n 3,200원\n 첫 번째 주차\n \n \n 희망대공원 주차료\n 400원\n 킥보드 찾으러 두 번째 주차\n \n \n\n\n지출\n\n\n \n \n 구분\n 금액\n 장소\n 비고\n \n \n \n \n 와이프님 옷\n 89,800원\n 세이브존\n 총 5벌\n \n \n 점심식사\n 15,500원\n 버거킹\n  \n \n \n 주차료\n 3,600원\n 희망대공원 주차장\n 2회\n \n \n\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 짬뽕\n  \n \n \n 점심\n 버거킹\n  \n \n \n 저녁\n 소세지, 쌀밥 등\n  \n \n \n\n\n"]
Title : 신구대학교 수목원 방문 + 회사 어린이날 행사
URL : /diary/2022/10/29/%EC%8B%A0%EA%B5%AC%EB%8C%80%ED%95%99%EA%B5%90%EC%88%98%EB%AA%A9%EC%9B%90.html
Description : 2022년 10월 29일 일기입니다. 오전에는 회사 어린이날 행사로, 오후에는 신구대학교 수목원 구경으로 분주한 하루를 보냈습니다.
Content : 요약
2022년 10월 29일은 분주한 하루였습니다.
오전에는 회사 어린이날 행사에 참여했고,
오후에는 신구대학교 수목원을 구경했습니다.

회사 어린이날 행사 (오전)

오전에는 회사 어린이날 행사에 참여했습니다.
회사에서 진행하는 온라인 퀴즈에 참여해서 10등이라는 좋은 성적을 받았습니다.
비누를 만들어보는 메이커 교육도 받았고,
크림 떡볶이 밀키트를 이용해서 쿠킹 클래스도 진행했습니다.


✅ 온라인 퀴즈에 참여 (10등)
✅ 메이커 교육 참여 (비누 만들기)
✅ 쿠킹 클래스 참여 (크림 떡볶이 만들기)


온라인 퀴즈



작년 회사 어린이집 행사때 퀴즈는 너무 어려웠습니다.
다들 너무 잘해서 중간을 하는 것도 힘들었습니다.
그래서 이번 퀴즈 역시도 중간도 못 하겠다고 생각을 했습니다.

여러가지 이유들로 틀린 문제들이 많았지만, 의외로 우리 가족의 등수가 높았습니다.
70여명 중에서 10등을 했습니다.
25등 안에 들면 선물을 줍니다.
어떤 선물일까?

메이커 교육 (비누 만들기)



비누 만들기 교육은 원어민 선생님께서 수업을 진행하셨다.
우리 아들이 정말 좋아했다.
비누가 생각보다 예쁘고 향긋하게 만들어졌다.
다음에 기회가 된다면 첫째 아들과 또 만들어볼 수 있는 기회를 가지고 싶다.

쿠킹 클래스 (크림 떡볶이)



작년에는 바질크림빠네파스타 밀키트로 쿠킹 클래스를 진행했습니다.
지난번 크림파스타는 솔직히 별로 맛이 없었습니다.
그래서 이번 크림떡볶이도 별로 맛이 없을 것이라고 생각했습니다.

지난번 쿠킹 클래스 행사






[프레시지 326] 바질크림빠네파스타 밀키트 - 아들이랑 파스타 만들어보기
요즘 밀키트 참 유행하는 것 같네요. 밀키트 분야는 코로나 때문에 많이 커진 사업 영역이 아닐까 싶습니다...









이번에는 ‘프레시밀’의 ‘크림 떡볶이’라는 밀키트였는데,
지난번보다 훨씬 더 맛이 좋았습니다.
우리 가족 모두 맛있게 먹었습니다.
쿠킹클래스에 참여했던 다른 많은 가족들도 크림 떡볶이가 맛있다고 표현해주셨습니다.


기억해두자! 맛있는 크림 떡볶이 밀키트! 프레시밀 크림 떡볶이!


신구대학교 수목원 구경 (오후)



오후는 병근이네와 신구대학교 수목원에 다녀왔다.

등장인물




구분
내용





 


우리 첫째 아들
 


우리 둘째 아들
 


병근이
 


병근이 둘째 딸
 




관람료




구분
수량
금액
비고




성인 입장료
1매
7,000원
 


유아 입장료 (36개월 이상)
1매
3,000원
 


유아 입장료 (36개월 미만)
1매
0원
 





36개월 미만 유아는 입장료 무료!


네이버 블로그에 작성한 후기






신구대학교 식물원 아주 좋았다. 구석구석 다니려면 유모차는 굉장히 힘들다.
신구대학교 수목원 아니고요! 신구대학교 식물원으로 검색해야지 제대로 나오네요. 어제 다녀왔음에도 불구하고 이름을 헷갈리는 나란 남자! 요즘 기억력이 산산조각 수준입니다. 기억 조각 모음을 위해서 오늘도 열심히 블로그를 씁니다.
(2022-10-29 작성)








우리카드 습득

신구대학교 식물원 관람을 마치고 나오는 길에 바닥에 떨어진 우리카드를 주웠다.
우리카드 고객센터에 전화해서 카드 습득신고를 했다.


우리카드 고객센터 : 1588-9955


카드의 주인은 20대로 보이는 여자였다.
우리집까지 버스를 타고 오셔서 카드를 받아가셨다.
어디까지나 추측일 뿐이지만, 신구대학교 수목원 직원인 것 같았다.

오늘 식사 이력




구분
메뉴
비고




아침
쫄면
 


점심
크림떡볶이
FRESHMEAL 밀키트


저녁
떡볶이, 유부초밥, 만두
 



["요약\n2022년 10월 29일은 분주한 하루였습니다. \n오전에는 회사 어린이날 행사에 참여했고, \n오후에는 신구대학교 수목원을 구경했습니다.\n\n회사 어린이날 행사 (오전)\n\n오전에는 회사 어린이날 행사에 참여했습니다. \n회사에서 진행하는 온라인 퀴즈에 참여해서 10등이라는 좋은 성적을 받았습니다. \n비누를 만들어보는 메이커 교육도 받았고, \n크림 떡볶이 밀키트를 이용해서 쿠킹 클래스도 진행했습니다.\n\n\n ✅ 온라인 퀴즈에 참여 (10등)\n ✅ 메이커 교육 참여 (비누 만들기)\n ✅ 쿠킹 클래스 참여 (크림 떡볶이 만들기)\n\n\n온라인 퀴즈\n\n\n\n작년 회사 어린이집 행사때 퀴즈는 너무 어려웠습니다. \n다들 너무 잘해서 중간을 하는 것도 힘들었습니다. \n그래서 이번 퀴즈 역시도 중간도 못 하겠다고 생각을 했습니다.\n\n여러가지 이유들로 틀린 문제들이 많았지만, 의외로 우리 가족의 등수가 높았습니다. \n70여명 중에서 10등을 했습니다. \n25등 안에 들면 선물을 줍니다. \n어떤 선물일까?\n\n메이커 교육 (비누 만들기)\n\n\n\n비누 만들기 교육은 원어민 선생님께서 수업을 진행하셨다. \n우리 아들이 정말 좋아했다. \n비누가 생각보다 예쁘고 향긋하게 만들어졌다. \n다음에 기회가 된다면 첫째 아들과 또 만들어볼 수 있는 기회를 가지고 싶다.\n\n쿠킹 클래스 (크림 떡볶이)\n\n\n\n작년에는 바질크림빠네파스타 밀키트로 쿠킹 클래스를 진행했습니다. \n지난번 크림파스타는 솔직히 별로 맛이 없었습니다.\n그래서 이번 크림떡볶이도 별로 맛이 없을 것이라고 생각했습니다.\n\n지난번 쿠킹 클래스 행사\n\n\n\n\n \n \n [프레시지 326] 바질크림빠네파스타 밀키트 - 아들이랑 파스타 만들어보기\n 요즘 밀키트 참 유행하는 것 같네요. 밀키트 분야는 코로나 때문에 많이 커진 사업 영역이 아닐까 싶습니다...\n \n \n \n \n \n \n\n\n\n이번에는 ‘프레시밀’의 ‘크림 떡볶이’라는 밀키트였는데, \n지난번보다 훨씬 더 맛이 좋았습니다. \n우리 가족 모두 맛있게 먹었습니다. \n쿠킹클래스에 참여했던 다른 많은 가족들도 크림 떡볶이가 맛있다고 표현해주셨습니다.\n\n\n 기억해두자! 맛있는 크림 떡볶이 밀키트! 프레시밀 크림 떡볶이!\n\n\n신구대학교 수목원 구경 (오후)\n\n\n\n오후는 병근이네와 신구대학교 수목원에 다녀왔다.\n\n등장인물\n\n\n \n \n 구분\n 내용\n \n \n \n \n 나\n  \n \n \n 우리 첫째 아들\n  \n \n \n 우리 둘째 아들\n  \n \n \n 병근이\n  \n \n \n 병근이 둘째 딸\n  \n \n \n\n\n관람료\n\n\n \n \n 구분\n 수량\n 금액\n 비고\n \n \n \n \n 성인 입장료\n 1매\n 7,000원\n  \n \n \n 유아 입장료 (36개월 이상)\n 1매\n 3,000원\n  \n \n \n 유아 입장료 (36개월 미만)\n 1매\n 0원\n  \n \n \n\n\n\n 36개월 미만 유아는 입장료 무료!\n\n\n네이버 블로그에 작성한 후기\n\n\n\n\n \n \n 신구대학교 식물원 아주 좋았다. 구석구석 다니려면 유모차는 굉장히 힘들다.\n 신구대학교 수목원 아니고요! 신구대학교 식물원으로 검색해야지 제대로 나오네요. 어제 다녀왔음에도 불구하고 이름을 헷갈리는 나란 남자! 요즘 기억력이 산산조각 수준입니다. 기억 조각 모음을 위해서 오늘도 열심히 블로그를 씁니다.\n (2022-10-29 작성) \n \n \n \n \n \n\n\n\n우리카드 습득\n\n신구대학교 식물원 관람을 마치고 나오는 길에 바닥에 떨어진 우리카드를 주웠다. \n우리카드 고객센터에 전화해서 카드 습득신고를 했다.\n\n\n 우리카드 고객센터 : 1588-9955\n\n\n카드의 주인은 20대로 보이는 여자였다. \n우리집까지 버스를 타고 오셔서 카드를 받아가셨다. \n어디까지나 추측일 뿐이지만, 신구대학교 수목원 직원인 것 같았다.\n\n오늘 식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n 쫄면\n  \n \n \n 점심\n 크림떡볶이\n FRESHMEAL 밀키트\n \n \n 저녁\n 떡볶이, 유부초밥, 만두\n  \n \n \n\n"]
Title : GitHub Pages Jekyll Liquid 문법 정리
URL : /github-pages/2022/10/28/liquid-syntax.html
Description : GitHub Pages Jekyll Liquid 문법 정리
Content : 필터

abs (절대값 구하기)

절대값을 구하는 필터


{{ -17 | abs }}
{{ 4 | abs }}



17
4


newline_to_br (개행을 br 테그로 변환)

개행을 br 테그로 변환


{% capture string_with_newlines %}
Hello
there
{% endcapture %}





<br />
Hello<br />
there<br />



strip_html (html 테그 제거)

HTML 테그를 제거하는 필터






{{ “Have you read Ulysses?”
strip_html }}





Hello
there



Have you read Uiysses?


참고할만한 페이지






Liquid template language
Documentation for the Liquid template language, created by Shopify.









["필터\n\nabs (절대값 구하기)\n\n절대값을 구하는 필터\n\n\n{{ -17 | abs }}\n{{ 4 | abs }}\n\n\n\n17\n4\n\n\nnewline_to_br (개행을 br 테그로 변환)\n\n개행을 br 테그로 변환\n\n\n{% capture string_with_newlines %}\nHello\nthere\n{% endcapture %}\n\n\n\n\n\n<br />\nHello<br />\nthere<br />\n\n\n\nstrip_html (html 테그 제거)\n\nHTML 테그를 제거하는 필터\n\n\n\n\n \n \n {{ “Have you read Ulysses?”\n strip_html }}\n \n \n\n\n\nHello\nthere\n\n\n\nHave you read Uiysses?\n\n\n참고할만한 페이지\n\n\n\n\n \n \n Liquid template language\n Documentation for the Liquid template language, created by Shopify.\n \n \n \n \n \n \n\n\n\n"]
Title : jekyll-paginate 플러그인을 사용해서 페이지 나누기
URL : /github-pages/2022/10/28/how-to-use-paginate-with-jekyll-paginate-plugin.html
Description : GitHub Pages에서 페이지를 나누는 방법 설명
Content : 웹사이트들 중에는 여러 페이지 목록을 숫자로 나눠서 표기하는 경우가 많다.
GitHub Pages에서는 jekyll-paginate 플러그인을 통해서
페이지를 나눠서 표시하는 기능을 제공한다.

요약

GitHub Pages에서 jekyll-paginate 플러그인을 사용하려면
아래 2개 파일을 편집하면 된다.

_config.yml 파일 편집

plugins:
- jekyll-paginate
paginate: 5
paginate_path: "/blog/page:num"


/index.html 파일 편집

---
layout: null
---

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{% for post in site.posts %}
{% unless post.published == false %}
<url>
<loc>{{ site.url }}{{ post.url }}</loc>
{% if post.sitemap.lastmod %}
<lastmod>{{ post.sitemap.lastmod | date: "%Y-%m-%d" }}</lastmod>
{% elsif post.date %}
<lastmod>{{ post.date | date_to_xmlschema }}</lastmod>
{% else %}
<lastmod>{{ site.time | date_to_xmlschema }}</lastmod>
{% endif %}
{% if post.sitemap.changefreq %}
<changefreq>{{ post.sitemap.changefreq }}</changefreq>
{% else %}
<changefreq>monthly</changefreq>
{% endif %}
{% if post.sitemap.priority %}
<priority>{{ post.sitemap.priority }}</priority>
{% else %}
<priority>0.5</priority>
{% endif %}
</url>
{% endunless %}
{% endfor %}
</urlset>



변수




변수
용도
비고




site.paginate_path
pagenate 된 페이지들이 서비스될 경로
 


paginator.page
페이지 번호
 


paginator.per_page
페이지 별로 표시될 포스트 개수
 


paginator.posts
이 페이지에 포함된 포스트들
 


paginator.total_posts
전체 포스트 개수
 


paginator.total_pages
전체 페이지 개수
 


paginator.previous_path
이전 페이지 번호
 


paginator.previous_page_path
이전 페이지 경로
 


paginator.next_page
다음 페이지 번호
 


paginator.next_page_path
다음 페이지 경로
 




제약사항


paginate를 이용하기 위해서는 반드시 /index.html 파일만 가능하다.
permalink를 이용해서는 안 된다.
md 파일이 아닌 html 형식의 파일만 이용 가능하다.


트러블 슈팅

index.html 파일을 찾지 못하는 경우

문제 현상
Pagination: Pagination is enabled, but I couldn’t find an index.html page to use as the pagination template. Skipping pagination.

원인
만약 Build 시에 위와 같은 에러가 발생했다면,
index.html 파일을 찾지 못해서다.

대책
반드시 루트 경로에 index.html 파일을 작성해야 한다.

참고할 만한 페이지






Pagination
With many websites — especially blogs — it’s very common to break the main listing of posts up into smaller lists and display them over multiple pages. Jekyll offers a pagination plugin, so you can automatically generate the appropriate files and folders you need for paginated listings.









http://jekyllrb.com/docs/pagination

이상입니다.
["웹사이트들 중에는 여러 페이지 목록을 숫자로 나눠서 표기하는 경우가 많다. \nGitHub Pages에서는 jekyll-paginate 플러그인을 통해서 \n페이지를 나눠서 표시하는 기능을 제공한다.\n\n요약\n\nGitHub Pages에서 jekyll-paginate 플러그인을 사용하려면 \n아래 2개 파일을 편집하면 된다.\n\n_config.yml 파일 편집\n\nplugins:\n - jekyll-paginate\npaginate: 5\npaginate_path: \"/blog/page:num\"\n\n\n/index.html 파일 편집\n\n---\nlayout: null\n---\n\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\n{% for post in site.posts %}\n {% unless post.published == false %}\n <url>\n <loc>{{ site.url }}{{ post.url }}</loc>\n {% if post.sitemap.lastmod %}\n <lastmod>{{ post.sitemap.lastmod | date: \"%Y-%m-%d\" }}</lastmod>\n {% elsif post.date %}\n <lastmod>{{ post.date | date_to_xmlschema }}</lastmod>\n {% else %}\n <lastmod>{{ site.time | date_to_xmlschema }}</lastmod>\n {% endif %}\n {% if post.sitemap.changefreq %}\n <changefreq>{{ post.sitemap.changefreq }}</changefreq>\n {% else %}\n <changefreq>monthly</changefreq>\n {% endif %}\n {% if post.sitemap.priority %}\n <priority>{{ post.sitemap.priority }}</priority>\n {% else %}\n <priority>0.5</priority>\n {% endif %}\n </url>\n {% endunless %}\n{% endfor %}\n </urlset>\n\n\n\n변수\n\n\n \n \n 변수\n 용도\n 비고\n \n \n \n \n site.paginate_path\n pagenate 된 페이지들이 서비스될 경로\n  \n \n \n paginator.page\n 페이지 번호\n  \n \n \n paginator.per_page\n 페이지 별로 표시될 포스트 개수\n  \n \n \n paginator.posts\n 이 페이지에 포함된 포스트들\n  \n \n \n paginator.total_posts\n 전체 포스트 개수\n  \n \n \n paginator.total_pages\n 전체 페이지 개수\n  \n \n \n paginator.previous_path\n 이전 페이지 번호\n  \n \n \n paginator.previous_page_path\n 이전 페이지 경로\n  \n \n \n paginator.next_page\n 다음 페이지 번호\n  \n \n \n paginator.next_page_path\n 다음 페이지 경로\n  \n \n \n\n\n제약사항\n\n\n paginate를 이용하기 위해서는 반드시 /index.html 파일만 가능하다.\n permalink를 이용해서는 안 된다.\n md 파일이 아닌 html 형식의 파일만 이용 가능하다.\n\n\n트러블 슈팅\n\nindex.html 파일을 찾지 못하는 경우\n\n문제 현상\nPagination: Pagination is enabled, but I couldn’t find an index.html page to use as the pagination template. Skipping pagination.\n\n원인\n만약 Build 시에 위와 같은 에러가 발생했다면, \nindex.html 파일을 찾지 못해서다.\n\n대책\n반드시 루트 경로에 index.html 파일을 작성해야 한다.\n\n참고할 만한 페이지\n\n\n\n\n \n \n Pagination\n With many websites — especially blogs — it’s very common to break the main listing of posts up into smaller lists and display them over multiple pages. Jekyll offers a pagination plugin, so you can automatically generate the appropriate files and folders you need for paginated listings.\n \n \n \n \n \n \n\n\n\nhttp://jekyllrb.com/docs/pagination\n\n이상입니다.\n"]
Title : 분당서울안과의원에서 첫째 아들 진료
URL : /diary/2022/10/28/%EC%95%BC%ED%83%91%EC%84%9C%EC%9A%B8%EC%95%88%EA%B3%BC%EC%9D%98%EC%9B%90.html
Description : 6살 첫째 아들이 눈을 심하게 깜빡거려서 진료 받음. 원인은 알레르기였다.
Content : 6살 첫째 아들의 심한 눈 깜빡임
6살 첫째 아들이 눈을 심하게 깜빡거렸다.
어린이집 선생님 뿐만 아니라 어린이집의 다른 반 선생님까지
첫째 아들이 눈을 심하게 깜빡인다고 알려주셨다.
퇴근하고 분당서울안과의원에서 진료를 봤다.

분당서울안과의원 진료 결과
눈 깜빡임의 원인은 알레르기였다고 했다.
아마 이전부터 이런 증상이 있었을 것이라고 했다.
안약으로 치료를 한다고 하더라도 다시 재발할 수 있다고 했다.
나중에는 자연스럽게 치유될 수도 있다고 했다.
도시에 사는 아이들에게는 아토피나 알레르기가 흔한 증상이다.

치료
치료 방법은 안약을 하루에 한 번씩 넣어주는 것이다.
증상이 심하면 최대 2번까지 안약을 투여할 수 있다.
안약과 함께 인공눈물도 처방을 받았다.
증상이 심할 때 인공 눈물을 넣어주면 눈이 편해지는데 도움이 된다고 했다.

나인약국
처방전을 가지고 약국 바로 맞은편에 있는 나인약국에 들렸다.
성남시 아동수당카드로 결제했다.
약값은 무려 1.1만원이나 나왔다.




구분
비용
비고




안약
 
 


인공 눈물
 
 




회사 PC 반납
회사에서 새 PC를 지급받아서 사용한지 제법 오래 되었다.
기존 PC는 반납을 해야 하는데, 그 동안 귀차니즘 때문에 반납을 미뤘었다.
계속 반납하지 않으면 반납을 안해도 될 것이라고 생각했다.
예상과는 달리, PC 반납 독려 메일이 수신되었다.
결국, PC를 잘 팩킹해서 문서수발실에 반납을 했다.

회사 할로윈 행사 준비
10월 30일은 할로윈 데이는 일요일이다.
그래서 그 바로 다음 날인 10월 31일에 회사에서 행사를 진행한다.
행사에 사용할 출력물들을 가위로 자르는 일을 좀 도와줬다.

식사




구분
메뉴
비고


아침
볶음밥
 


점심
어묵탕
해장 메뉴로 훌륭했다


저녁
열라면, 핫도그, 소시지
너무 과식했다. 반성!



["6살 첫째 아들의 심한 눈 깜빡임\n6살 첫째 아들이 눈을 심하게 깜빡거렸다. \n어린이집 선생님 뿐만 아니라 어린이집의 다른 반 선생님까지 \n첫째 아들이 눈을 심하게 깜빡인다고 알려주셨다. \n퇴근하고 분당서울안과의원에서 진료를 봤다.\n\n분당서울안과의원 진료 결과\n눈 깜빡임의 원인은 알레르기였다고 했다. \n아마 이전부터 이런 증상이 있었을 것이라고 했다. \n안약으로 치료를 한다고 하더라도 다시 재발할 수 있다고 했다. \n나중에는 자연스럽게 치유될 수도 있다고 했다. \n도시에 사는 아이들에게는 아토피나 알레르기가 흔한 증상이다.\n\n치료\n치료 방법은 안약을 하루에 한 번씩 넣어주는 것이다. \n증상이 심하면 최대 2번까지 안약을 투여할 수 있다. \n안약과 함께 인공눈물도 처방을 받았다. \n증상이 심할 때 인공 눈물을 넣어주면 눈이 편해지는데 도움이 된다고 했다.\n\n나인약국\n처방전을 가지고 약국 바로 맞은편에 있는 나인약국에 들렸다. \n성남시 아동수당카드로 결제했다. \n약값은 무려 1.1만원이나 나왔다.\n\n\n \n \n 구분\n 비용\n 비고\n \n \n \n \n 안약\n  \n  \n \n \n 인공 눈물\n  \n  \n \n \n\n\n회사 PC 반납\n회사에서 새 PC를 지급받아서 사용한지 제법 오래 되었다. \n기존 PC는 반납을 해야 하는데, 그 동안 귀차니즘 때문에 반납을 미뤘었다. \n계속 반납하지 않으면 반납을 안해도 될 것이라고 생각했다. \n예상과는 달리, PC 반납 독려 메일이 수신되었다. \n결국, PC를 잘 팩킹해서 문서수발실에 반납을 했다.\n\n회사 할로윈 행사 준비\n10월 30일은 할로윈 데이는 일요일이다. \n그래서 그 바로 다음 날인 10월 31일에 회사에서 행사를 진행한다. \n행사에 사용할 출력물들을 가위로 자르는 일을 좀 도와줬다.\n\n식사\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n 아침\n 볶음밥\n  \n \n \n 점심\n 어묵탕\n 해장 메뉴로 훌륭했다\n \n \n 저녁\n 열라면, 핫도그, 소시지\n 너무 과식했다. 반성!\n \n \n\n"]
Title : 성남시 고등동 맛집 연탄불포차 닭발의 재발견
URL : /diary/2022/10/27/%EC%97%B0%ED%83%84%EB%B6%88%ED%8F%AC%EC%B0%A8-%EC%84%B1%EB%82%A8%EC%8B%9C-%EA%B3%A0%EB%93%B1%EB%8F%99-%EB%A7%9B%EC%A7%91.html
Description : 육사시미가 인상적인 곳입니다. 닭발도 처음 시도해봤는데 정말 맛있고 푸짐했습니다.
Content : 고등동 주민이 추천하는 고등동 맛집

누군가 나에게 성남시 고등동에서 최고의 맛집을 꼽으라고 한다면,
망설임 없이 를 추천하고 싶다.
신선한 육사시미가 인상적이다.
항상 육사시미만 먹다가 오늘은 닭발도 시도해봤는데 닭발도 맛있었다.


✅ 고등동 맛집 연탄불포차
✅ 육사시미가 인상적
✅ 닭발도 맛있다.


기본 상차림

기본적으로 깔리는 반찬들은 훌륭하다.
사장님께서는 근처에 있는 밭에서 농사를 지으시는데,
직접 농사를 지어서 키운 농작물로 만드신 반찬들이 간혹 손님상에 올라오곤 한다.

사라다(과일 샐러드)도 괜찮았고, 꼬들꼬들한 생선 무침도 맛이 있었다.
맛집은 반찬만 먹어보면 알 수 있다.
반찬이 맛있는 집이면 메인 메뉴도 맛있다.


✅ 반찬이 맛있는 집이 맛집이다.
✅ 직접 재배한 제철 반찬들도 간혹 올라온다.


육사시미

이 집의 최고 메뉴는 단언컨데 육사시미다.
신선하면서도 푸짐한 육사시미는 맛도 좋고 가격도 착하다.
육사시미는 미리 예약해야 맛을 볼 수 있다.


✅ 신선하다.
✅ 맛이 좋다.
✅ 가격이 착하다.
✅ 미리 예약 필수!



육사시미는 잡내가 전혀 없으면서 입 안에서 부드럽게 씹힌다.
워낙 맛이 좋다보니 소주가 술술 들어갔다.
정확하게 2주만에 입에 술을 댔다.
안주가 좋아서 그런지 속에서 술을 잘 받아줬다.


군침도는 비주얼이다.
고기가 얼마나 신선한지 눈으로 확인할 수 있다.
판타스틱! 뽠따스틱!

닭발 (1.8만원)

이 집은 육사시미가 정말 인상적인 곳이다.
방문할때마다 육사시미를 꼭 먹는다.
오늘 처음으로 닭발을 시도해봤는데, 닭발도 정말 맛있었다.
닭발 하나를 입에 넣으면 바로 생강향이 느껴진다.
생강향으로 닭발의 잡내를 깔끔하게 잡았다는 생각이 든다.


✅ 닭발도 맛있다.
✅ 생강향이 인상적
✅ 잡내가 전혀 없다.



술이 무한대로 들어간다.
닭발이 식으면 사장님께서 연탄불에 다시 데워주신다.
사장님이 굉장히 친절하시다.
사장님이 굉장히 친절해지셨다.

지난 방문기






성남시 고등동 회식장소 연탄불포차 육사시미 찐맛집
여기는 못 먹어도 무조건 고! 무조건 재방문해야 되는 곳입니다. 맛집 블로그를 오래 써왔지만 여기처럼 강력하게 추천하고 싶은 곳은 처음인 듯...
(2022-07-19 작성)








연탄불포차 정보

주소 : 경기도 성남시 수정구 대왕판교로 976번길 9-6
전화번호 : 010-8780-8515


2차로 갔던 투다리






성남시 고등동 하이볼 맛볼 수 있는 곳 《투다리 고등호반점》
조니워커 하이볼이 정말 인상적이었던 투다리 고등호반점 방문기
(2022-10-27 작성)








["고등동 주민이 추천하는 고등동 맛집\n\n누군가 나에게 성남시 고등동에서 최고의 맛집을 꼽으라고 한다면, \n망설임 없이 를 추천하고 싶다. \n신선한 육사시미가 인상적이다. \n항상 육사시미만 먹다가 오늘은 닭발도 시도해봤는데 닭발도 맛있었다.\n\n\n ✅ 고등동 맛집 연탄불포차\n ✅ 육사시미가 인상적\n ✅ 닭발도 맛있다.\n\n\n기본 상차림\n\n기본적으로 깔리는 반찬들은 훌륭하다. \n사장님께서는 근처에 있는 밭에서 농사를 지으시는데, \n직접 농사를 지어서 키운 농작물로 만드신 반찬들이 간혹 손님상에 올라오곤 한다.\n\n사라다(과일 샐러드)도 괜찮았고, 꼬들꼬들한 생선 무침도 맛이 있었다. \n맛집은 반찬만 먹어보면 알 수 있다. \n반찬이 맛있는 집이면 메인 메뉴도 맛있다.\n\n\n ✅ 반찬이 맛있는 집이 맛집이다.\n ✅ 직접 재배한 제철 반찬들도 간혹 올라온다.\n\n\n육사시미\n\n이 집의 최고 메뉴는 단언컨데 육사시미다. \n신선하면서도 푸짐한 육사시미는 맛도 좋고 가격도 착하다. \n육사시미는 미리 예약해야 맛을 볼 수 있다.\n\n\n ✅ 신선하다.\n ✅ 맛이 좋다.\n ✅ 가격이 착하다.\n ✅ 미리 예약 필수!\n\n\n\n육사시미는 잡내가 전혀 없으면서 입 안에서 부드럽게 씹힌다. \n워낙 맛이 좋다보니 소주가 술술 들어갔다. \n정확하게 2주만에 입에 술을 댔다. \n안주가 좋아서 그런지 속에서 술을 잘 받아줬다.\n\n\n군침도는 비주얼이다. \n고기가 얼마나 신선한지 눈으로 확인할 수 있다. \n판타스틱! 뽠따스틱!\n\n닭발 (1.8만원)\n\n이 집은 육사시미가 정말 인상적인 곳이다. \n방문할때마다 육사시미를 꼭 먹는다. \n오늘 처음으로 닭발을 시도해봤는데, 닭발도 정말 맛있었다. \n닭발 하나를 입에 넣으면 바로 생강향이 느껴진다. \n생강향으로 닭발의 잡내를 깔끔하게 잡았다는 생각이 든다.\n\n\n ✅ 닭발도 맛있다.\n ✅ 생강향이 인상적\n ✅ 잡내가 전혀 없다.\n\n\n\n술이 무한대로 들어간다. \n닭발이 식으면 사장님께서 연탄불에 다시 데워주신다. \n사장님이 굉장히 친절하시다.\n사장님이 굉장히 친절해지셨다.\n\n지난 방문기\n\n\n\n\n \n \n 성남시 고등동 회식장소 연탄불포차 육사시미 찐맛집\n 여기는 못 먹어도 무조건 고! 무조건 재방문해야 되는 곳입니다. 맛집 블로그를 오래 써왔지만 여기처럼 강력하게 추천하고 싶은 곳은 처음인 듯...\n (2022-07-19 작성) \n \n \n \n \n \n\n\n\n연탄불포차 정보\n\n 주소 : 경기도 성남시 수정구 대왕판교로 976번길 9-6\n 전화번호 : 010-8780-8515\n\n\n2차로 갔던 투다리\n\n\n\n\n \n \n 성남시 고등동 하이볼 맛볼 수 있는 곳 《투다리 고등호반점》\n 조니워커 하이볼이 정말 인상적이었던 투다리 고등호반점 방문기\n (2022-10-27 작성) \n \n \n \n \n \n\n\n\n"]
Title : SK 인터넷 공인 IP 개수가 무려 4개나 된다.
URL : /it/2022/10/26/KT인터넷공인IP개수.html
Description : 집에서 사용중인 에스케이 인터넷 구성 정보 메모
Content : 집에서 사용중인 SK 인터넷의 공인 IP 개수가 무려 4개나 된다.
덕분에 공인IP를 가진 서버를 2개~3개나 운영할 수 있는 장점이 있다.




WAN
 
 
 


GPON(GNT-2040N)
 
 
 


 
 
 
 


공인IP #1
공인IP #2
공인IP #3
공인IP #4


라즈베리파이
PC
인터넷TV
공유기


 
 
 
NIS-HM1624FS



["집에서 사용중인 SK 인터넷의 공인 IP 개수가 무려 4개나 된다. \n덕분에 공인IP를 가진 서버를 2개~3개나 운영할 수 있는 장점이 있다.\n\n\n \n \n WAN\n  \n  \n  \n \n \n GPON(GNT-2040N)\n  \n  \n  \n \n \n  \n  \n  \n  \n \n \n 공인IP #1\n 공인IP #2\n 공인IP #3\n 공인IP #4\n \n \n 라즈베리파이\n PC\n 인터넷TV\n 공유기\n \n \n  \n  \n  \n NIS-HM1624FS\n \n \n\n"]
Title : 트위터 카드 검증 사이트에서 Unable to render Card preview 에러 발생
URL : /github-pages/2022/10/26/twitter-card-varlidator-unable-to-render-card-preview.html
Description : Twitter Card Validator에서 GitHub Pages 글 검증시에 Unable to render Card preview 에러가 발생하는 문제
Content : 트위터 카드란?

웹사이트나 블로그의 운영 목적은 최대한 많은 사람들에게
콘텐츠를 확산시키기 위함입니다.
더 많은 트래픽은 더 많은 광고 수익을 의미합니다.
많은 블로그들이 양질의 콘텐츠 작성을 위해 노력합니다.
동시에 콘텐츠를 페이스북, 트위터 등의 SNS를 통해 퍼트립니다.

트위터 카드는 트위터를 통해서 공유되는 페이지의 미리 보기를 제공합니다.
이를 통해서 사용자는 링크된 페이지의 정보를 직관적이고 빠르게 파악합니다.


HTML 메타 테그(Open Graph)

트위터 카드는 HTML에 포함된 메타 테그에서 트위터 관련 정보를 이용합니다.
아래는 HTML 헤더에 포함된 트위터 관련 오픈그래프 정보입니다.

<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:image" content="https://boyinblue.github.io/assets/logo.png" />
<meta property="twitter:title" content="현업 SW 개발자의 연구 노트" />



`twitter:card`
트위터 카드에 표시될 형식을 알려줍니다.
`summary_large_image`는 위의 예시처럼 큰 이미지를 이용합니다.

'twitter:image'
트위터 카드에 표시될 이미지를 알려줍니다.

'twitter:title'
트위터 카드에 표시될 제목을 알려줍니다.


트위터 카드 검증 페이지

Twitter Card Validator

위의 홈페이지에 접속하셔서 체크할 페이지의 URL을 입력하시면 됩니다.

트위터 카드 검증 실패



제가 작성한 페이지를 입력했더니 위의 화면처럼 “Unable to render Card preview”라는 메시지를 토해냅니다.

트위터 커뮤니티 관련 글

해결 방법을 확인하기 위해서 구글에서 Unable to render Card preview 키워드로 검색해보니 이와 비슷한 문제로 고생하고 있는 개발자들이 많이 있었습니다.

해결 방법

트위터 카드 검증 사이트에서는 에러가 발생했지만,
실제로 트위터로 업로드를 해봤더니 정상적으로 트위터 카드가 발행되었습니다.



다만, 시간이 오래 걸립니다. 거의 10분을 소요된 것 같습니다.
위의 화면에서 상당한 지연이 발생한 것을 제외하고는
큰 문제 없이 트위터 카드를 발행할 수 있었습니다.

결론

트위터 카드 검증 페이지에서 `Unable to render Card preview’
에러가 발생하더라도 트위터 카드 발행이 가능할 수 있습니다.
이 부분은 트위터 카드 검증 페이지의 오류로 보입니다.

이 떄는 트위터 관련 메타 테그가 정상적인지 확인하시고,
이상이 없다고 생각되면 그냥 트윗을 날리세요.

트위터 카드 검증 페이지에서 검증 실패하더라도,
정상적으로 트위터 카드가 발행될 수 있기 때문입니다.
다만, 시간이 다소 오래 걸려서 인내심이 필요할 수 있습니다.
["트위터 카드란?\n\n웹사이트나 블로그의 운영 목적은 최대한 많은 사람들에게 \n콘텐츠를 확산시키기 위함입니다. \n더 많은 트래픽은 더 많은 광고 수익을 의미합니다. \n많은 블로그들이 양질의 콘텐츠 작성을 위해 노력합니다. \n동시에 콘텐츠를 페이스북, 트위터 등의 SNS를 통해 퍼트립니다.\n\n트위터 카드는 트위터를 통해서 공유되는 페이지의 미리 보기를 제공합니다. \n이를 통해서 사용자는 링크된 페이지의 정보를 직관적이고 빠르게 파악합니다. \n\n\nHTML 메타 테그(Open Graph)\n\n트위터 카드는 HTML에 포함된 메타 테그에서 트위터 관련 정보를 이용합니다.\n아래는 HTML 헤더에 포함된 트위터 관련 오픈그래프 정보입니다.\n\n<meta name=\"twitter:card\" content=\"summary_large_image\" />\n<meta property=\"twitter:image\" content=\"https://boyinblue.github.io/assets/logo.png\" />\n<meta property=\"twitter:title\" content=\"현업 SW 개발자의 연구 노트\" />\n\n\n\n `twitter:card`\n 트위터 카드에 표시될 형식을 알려줍니다.\n `summary_large_image`는 위의 예시처럼 큰 이미지를 이용합니다.\n\n 'twitter:image'\n 트위터 카드에 표시될 이미지를 알려줍니다.\n\n 'twitter:title'\n 트위터 카드에 표시될 제목을 알려줍니다.\n\n\n트위터 카드 검증 페이지\n\nTwitter Card Validator\n\n위의 홈페이지에 접속하셔서 체크할 페이지의 URL을 입력하시면 됩니다.\n\n트위터 카드 검증 실패\n\n\n\n제가 작성한 페이지를 입력했더니 위의 화면처럼 “Unable to render Card preview”라는 메시지를 토해냅니다.\n\n트위터 커뮤니티 관련 글\n\n해결 방법을 확인하기 위해서 구글에서 Unable to render Card preview 키워드로 검색해보니 이와 비슷한 문제로 고생하고 있는 개발자들이 많이 있었습니다.\n\n해결 방법\n\n트위터 카드 검증 사이트에서는 에러가 발생했지만, \n실제로 트위터로 업로드를 해봤더니 정상적으로 트위터 카드가 발행되었습니다.\n\n\n\n다만, 시간이 오래 걸립니다. 거의 10분을 소요된 것 같습니다. \n위의 화면에서 상당한 지연이 발생한 것을 제외하고는 \n큰 문제 없이 트위터 카드를 발행할 수 있었습니다.\n\n결론\n\n트위터 카드 검증 페이지에서 `Unable to render Card preview’ \n에러가 발생하더라도 트위터 카드 발행이 가능할 수 있습니다. \n이 부분은 트위터 카드 검증 페이지의 오류로 보입니다.\n\n이 떄는 트위터 관련 메타 테그가 정상적인지 확인하시고, \n이상이 없다고 생각되면 그냥 트윗을 날리세요.\n\n트위터 카드 검증 페이지에서 검증 실패하더라도, \n정상적으로 트위터 카드가 발행될 수 있기 때문입니다. \n다만, 시간이 다소 오래 걸려서 인내심이 필요할 수 있습니다.\n"]
Title : Beyond Compare에서 화이트 스페이스 표시하는 방법
URL : /beyond-compare/2022/10/25/Beyond-Compare-Visible-White-Space.html
Description : 공백은 스페이스나 텝으로 구성되어 있습니다. Beyond Compare에서 white space를 표시하는 방법을 설명합니다.
Content : 요약

Beyond Compare에서 화이트 스페이스(white space)를 표시하기 위해서는
View - Visible Whitespace 메뉴를 선택하면 된다.

White Space란?

White Space란 눈에는 그저 하얗게 보이는 공백 문자를 의미한다.
Space 나 Tab 으로 구성된 부분이다.

White Space의 중요성

SW 개발자에게 공백(white space)는 상당히 중요한 부분이다.
공백이 스페이스(0x20)로 구성되어 있는지, 텝으로 구성되어 있는지가
다르게 동작하는 경우가 있을 수 있기 때문이다.

C언어 인덴트 문제

C언어에서의 indent는 소스 코드의 가독성을 향상시키는데 도움이 된다.
인덴트를 공백 4개로 사용할 것인지, 공백 8개로 사용할 것인지는
프로그래머에게 아주 중요한 문제일 수 있다.

A와 B가 공동의 프로젝트를 진행한다고 가정해보자.
A의 개발 환경은 텝이 공백 4개에 해당하는 크기이고,
B는 텝이 공백 8개에 해당하는 크기이다.

A가 작업한 코드를 B가 열었을 때 텝이 공백 8개로 표기되는 문제가 발생한다.
이 때문에 indent는 텝을 사용하지 말고 스페이스로만 구성하도록 하는
code convention을 구성하는 팀도 있다.

파이썬은 indent가 문법의 일부이다.

파이썬에서는 인덴트가 단순한 가독성을 높이기 위한 측면 뿐만 아니라,
문법의 일부라고 할 수 있다.
파이썬에서는 { 또는 } 같은 명시적인 부호 없이
인덴트를 이용해서 코드 블록을 구분하기 때문이다.

따라서, 파이썬에서 인덴트가 맞지 않을 경우
indent 문법 오류를 발생시킬 수 있다.

Beyond Compare에서 white space 설정



Beyond Compare에서 화이트 스페이스(white space)를
표기할 수 있는 기능을 제공한다.

화이트 스페이스 설정 메뉴


메뉴에서 View를 선택한 이후에, Visible Whitespace를 선택하면 된다.


단축키

Alt + V + W 를 입력하면
Whitespace 표시를 토글링할 수 있다.
["요약\n\nBeyond Compare에서 화이트 스페이스(white space)를 표시하기 위해서는 \nView - Visible Whitespace 메뉴를 선택하면 된다.\n\nWhite Space란?\n\nWhite Space란 눈에는 그저 하얗게 보이는 공백 문자를 의미한다. \n Space 나 Tab 으로 구성된 부분이다.\n\nWhite Space의 중요성\n\nSW 개발자에게 공백(white space)는 상당히 중요한 부분이다. \n공백이 스페이스(0x20)로 구성되어 있는지, 텝으로 구성되어 있는지가 \n다르게 동작하는 경우가 있을 수 있기 때문이다.\n\nC언어 인덴트 문제\n\nC언어에서의 indent는 소스 코드의 가독성을 향상시키는데 도움이 된다. \n인덴트를 공백 4개로 사용할 것인지, 공백 8개로 사용할 것인지는 \n프로그래머에게 아주 중요한 문제일 수 있다.\n\nA와 B가 공동의 프로젝트를 진행한다고 가정해보자. \nA의 개발 환경은 텝이 공백 4개에 해당하는 크기이고, \nB는 텝이 공백 8개에 해당하는 크기이다.\n\nA가 작업한 코드를 B가 열었을 때 텝이 공백 8개로 표기되는 문제가 발생한다. \n이 때문에 indent는 텝을 사용하지 말고 스페이스로만 구성하도록 하는 \ncode convention을 구성하는 팀도 있다.\n\n파이썬은 indent가 문법의 일부이다.\n\n파이썬에서는 인덴트가 단순한 가독성을 높이기 위한 측면 뿐만 아니라, \n문법의 일부라고 할 수 있다. \n파이썬에서는 { 또는 } 같은 명시적인 부호 없이 \n인덴트를 이용해서 코드 블록을 구분하기 때문이다.\n\n따라서, 파이썬에서 인덴트가 맞지 않을 경우 \nindent 문법 오류를 발생시킬 수 있다.\n\nBeyond Compare에서 white space 설정\n\n\n\nBeyond Compare에서 화이트 스페이스(white space)를 \n표기할 수 있는 기능을 제공한다.\n\n화이트 스페이스 설정 메뉴\n\n\n 메뉴에서 View를 선택한 이후에, Visible Whitespace를 선택하면 된다.\n\n\n단축키\n\n Alt + V + W 를 입력하면 \nWhitespace 표시를 토글링할 수 있다.\n"]
Title : VS Code 단축키 설명
URL : /vscode/vs-code-shortcuts.html
Description : 소스코드 편집 스킬을 향상시켜줄 단축키들 설명
Content : Visual Studio Code 단축키
수많은 SW개발자들이 무료로 사용할 수 있는 Visual Studio Code 편집기를 사용하고 있습니다.
다양한 플랫폼에서 다양한 편집 기능을 무료로 사용할 수 있어서 아주 만족스러운 툴입니다.
몇 년 전 까지만해도 많은 개발자들이 Source Insight와 같은 유료 편집 프로그램들을 사용했었습니다.
요즘 젊은 개발자들은 Source Insight보다 vscode를 훨씬 더 많이 사용하는 추세입니다.

주의할 점은 vscode의 윈도우즈 단축키와 리눅스 단축키가 서로 상이하다는 것입니다.
리눅스의 단축키와 윈도우즈의 그것이 다른 부분에 대해서는 따로 표기해두겠습니다.

리눅스 단축키



vscode 단축키 확인하는 방법
Ctrl + P를 누른 후에, shortcuts를 입력하면 단축키를 확인하실 수 있습니다.
참고로, 단축키는 입맛에 맛에 설정이 가능합니다.

검색 기능

현재 페이지에서 검색
Ctrl + F

전체 페이지에서 검색
Ctrl + Shift + F

이동 기능

이전 커서 위치로 이동
Alt + ⬅️

다음 커서 위치로 이동
Alt + ➡️

정의로 이동
F12

라인 번호로 이동
Ctrl + G

선택 관련

확대 및 축소 관련

확대 (Zoom In)
Ctrl + +

축소 (Zoom Out)
Ctrl + -
["Visual Studio Code 단축키\n수많은 SW개발자들이 무료로 사용할 수 있는 Visual Studio Code 편집기를 사용하고 있습니다. \n다양한 플랫폼에서 다양한 편집 기능을 무료로 사용할 수 있어서 아주 만족스러운 툴입니다. \n몇 년 전 까지만해도 많은 개발자들이 Source Insight와 같은 유료 편집 프로그램들을 사용했었습니다. \n요즘 젊은 개발자들은 Source Insight보다 vscode를 훨씬 더 많이 사용하는 추세입니다.\n\n주의할 점은 vscode의 윈도우즈 단축키와 리눅스 단축키가 서로 상이하다는 것입니다. \n리눅스의 단축키와 윈도우즈의 그것이 다른 부분에 대해서는 따로 표기해두겠습니다.\n\n리눅스 단축키\n\n\n\nvscode 단축키 확인하는 방법\nCtrl + P를 누른 후에, shortcuts를 입력하면 단축키를 확인하실 수 있습니다. \n참고로, 단축키는 입맛에 맛에 설정이 가능합니다.\n\n검색 기능\n\n현재 페이지에서 검색\n Ctrl + F \n\n전체 페이지에서 검색\n Ctrl + Shift + F \n\n이동 기능\n\n이전 커서 위치로 이동\n Alt + ⬅️ \n\n다음 커서 위치로 이동\n Alt + ➡️ \n\n정의로 이동\n F12 \n\n라인 번호로 이동\n Ctrl + G \n\n선택 관련\n\n확대 및 축소 관련\n\n확대 (Zoom In)\n Ctrl + + \n\n축소 (Zoom Out)\n Ctrl + - \n"]
Title : 우분투 리눅스에서 입력할 수 있는 특수문자들
URL : /ubuntu/ubuntu-special-characters.html
Description : 우분투 리눅스에서 입력할 수 있는 다양한 특수문자 제공
Content : 윈도우즈는 특수문자 천국

윈도우즈 운영체제에서는 🪟 + . 단축키로
다양한 특수문자들을 입력할 수 있습니다.

우분투 리눅스는 특수 문자 입력 어려움

반면, 우분투 리눅스에서는 특수 문자 입력기가 없습니다.
이 때문에 특수문자 입력이 어렵습니다.

인기 특수 문자들

인기있는 특수문자들을 기록해둡니다.


🐍 : 파이썬, 뱀
👍 : 엄지척
😺 : 고양이
🙏 : 기도
❌ : 가위표
⭕ : 공표
🚫 : 금지
🆗 : OK
🆖 : NG
🔼 : 위로
🔽 : 아래로
▶️ : 오른쪽으로
◀️ : 왼쪽으로
⬅️ : 왼쪽 화살표
➡️ : 오른쪽 화살표
⬆️ : 위쪽 화살표
⬇️ : 아래쪽 화살표
✔️ : 체크 표시
✅ : 체크 표시
✍️ : 글을 쓰고 있는 손, 편집 버튼
✏️ : 연필, 편집 버튼
#️⃣ : #, sharp, 샵, 우물정
🪟 : 윈도우, 윈도우즈, 창문
🌐 : 웹브라우저
Ⓜ️ : 이메일, e-mail
📧 : 이메일, e-mail
📑 : 목록, 인덱스, 목차


표정
😀😁😂🤣😃😄😅😆😉😊😋😎😍😘🥰😗😙🥲😚☺️🙂🤗🤩🤔🤨😐😑😶😶‍🌫️🙄😏😣😥😮🤐😯😪😫🥱😴😌😛😜😝🤤😒😓😔😕🙃🤑😲☹️🙁😖😞😟😤😢😭😦😧😨😩🤯😬😮‍💨😰😱🥵🥶😳🤪😵😵‍💫🥴😠😡🤬😷🤒🤕🤢🤮🤧😇🥳🥸🥺🤠🤡🤥🤫🤭🧐🤓😈👿👹👺💀☠️👻👽👾🤖💩

동물
😺😸😹😻😼😽🙀😿😾🙈🙉🙊🐵🐶🐺🐱🦁🐯🦒🦊🦝🐮🐷🐗🐭🐹🐰🐻🐻‍❄️🐨🐼🐸🦓🐴🦄🐔🐲🐽🐾🐒🦍🦧🦮🐕‍🦺🐩🐕🐈🐈‍⬛🐅🐆🐎🦌🦬🦏🦛🐂🐃🐄🐖🐏🐑🐐🐪🐫🦙🦘🦥🦨🦡🐘🦣🐁🐀🦔🐇🐿️🦫🦎🐊🐢🐍🐉🦕🦖🦦🦈🐬🦭🐳🐋🐟🐠🐡🦐🦑🐙🦞🦀🐚🦆🐓🦃🦅🕊️🦢🦜🦩🦚🦉🦤🪶🐦🐧🐥🐤🐣🦇🦋🐌🐛🦟🪰🪱🦗🐜🪳🐝🪲🐞🦂🕷️🕸️🦠

괴물
🧞‍♀️🧞‍♂️🧞🧟‍♀️🧟‍♂️🧟🗣️👤👥🫂

신체
👁️👀🦴🦷👅👄🧠🫀🫁🦾🦿👣

활동
🤺⛷️🤼‍♀️🤼‍♂️🤼👯‍♀️👯‍♂️👯

관계
👩‍❤️‍👨👩🏻‍❤️‍👨🏻👩🏻‍❤️‍👨🏼👩🏻‍❤️‍👨🏽👩🏻‍❤️‍👨🏾👩🏻‍❤️‍👨🏿👩🏼‍❤️‍👨🏻👩🏼‍❤️‍👨🏼👩🏼‍❤️‍👨🏽👩🏼‍❤️‍👨🏾👩🏼‍❤️‍👨🏿👩🏽‍❤️‍👨🏻👩🏽‍❤️‍👨🏼👩🏽‍❤️‍👨🏽👩🏽‍❤️‍👨🏾👩🏽‍❤️‍👨🏿👩🏾‍❤️‍👨🏻👩🏾‍❤️‍👨🏼👩🏻👨🏻🧑🏻🧑🏻👧🏻👧🏻👦🏻🧒🏻👨🏻‍🦰🧓🏻👵🏻👵🏻🧑🏻‍🦰🧑🏻‍🦱👩🏻‍🦲👨🏻‍🦲👱🏻‍♂️👱🏻‍♀️🧑🏻‍🦳👨🏻‍🦳👩🏾‍❤️‍👨🏽👩🏾‍❤️‍👨🏾👩🏾‍❤️‍👨🏿👩🏿‍❤️‍👨🏻👩🏿‍❤️‍👨🏼👩🏿‍❤️‍👨🏽👩🏿‍❤️‍👨🏾👩🏿‍❤️‍👨🏿👩‍❤️‍👩👩🏻‍❤️‍👩🏻👩🏻‍❤️‍👩🏼👩🏻‍❤️‍👩🏽👩🏻‍❤️‍👩🏾👩🏻‍❤️‍👩🏿👩🏼‍❤️‍👩🏻👩🏼‍❤️‍👩🏼👩🏼‍❤️‍👩🏽👩🏼‍❤️‍👩🏾👩🏼‍❤️‍👩🏿👩🏽‍❤️‍👩🏻👩🏽‍❤️‍👩🏼👩🏽‍❤️‍👩🏽👩🏽‍❤️‍👩🏾👩🏽‍❤️‍👩🏿👩🏾‍❤️‍👩🏻👩🏾‍❤️‍👩🏼👩🏾‍❤️‍👩🏽👩🏾‍❤️‍👩🏾👩🏾‍❤️‍👩🏿👩🏿‍❤️‍👩🏻👩🏿‍❤️‍👩🏼👩🏿‍❤️‍👩🏽👩🏿‍❤️‍👩🏾👩🏿‍❤️‍👩🏿👨‍❤️‍👨👨🏻‍❤️‍👨🏻👨🏻‍❤️‍👨🏼👨🏻‍❤️‍👨🏽👨🏻‍❤️‍👨🏾👨🏻‍❤️‍👨🏿👨🏼‍❤️‍👨🏻👨🏼‍❤️‍👨🏼👨🏼‍❤️‍👨🏽👨🏼‍❤️‍👨🏾👨🏼‍❤️‍👨🏿👨🏽‍❤️‍👨🏻👨🏽‍❤️‍👨🏼👨🏽‍❤️‍👨🏽👨🏽‍❤️‍👨🏾👨🏽‍❤️‍👨🏿👨🏾‍❤️‍👨🏻👨🏾‍❤️‍👨🏼👨🏾‍❤️‍👨🏽👨🏾‍❤️‍👨🏾👨🏾‍❤️‍👨🏿👨🏿‍❤️‍👨🏻👨🏿‍❤️‍👨🏼👨🏿‍❤️‍👨🏽👨🏿‍❤️‍👨🏾👨🏿‍❤️‍👨🏿💑💑🏻💑🏼💑🏽💑🏾💑🏿🧑🏻‍❤️‍🧑🏼🧑🏻‍❤️‍🧑🏽🧑🏻‍❤️‍🧑🏾🧑🏻‍❤️‍🧑🏿🧑🏼‍❤️‍🧑🏻🧑🏼‍❤️‍🧑🏽🧑🏼‍❤️‍🧑🏾🧑🏼‍❤️‍🧑🏿🧑🏽‍❤️‍🧑🏻🧑🏽‍❤️‍🧑🏼🧑🏽‍❤️‍🧑🏾🧑🏽‍❤️‍🧑🏿🧑🏾‍❤️‍🧑🏻🧑🏾‍❤️‍🧑🏼🧑🏾‍❤️‍🧑🏽🧑🏾‍❤️‍🧑🏿🧑🏿‍❤️‍🧑🏻🧑🏿‍❤️‍🧑🏼🧑🏿‍❤️‍🧑🏽🧑🏿‍❤️‍🧑🏾👩‍❤️‍💋‍👨👩🏻‍❤️‍💋‍👨🏻👩🏻‍❤️‍💋‍👨🏼👩🏻‍❤️‍💋‍👨🏽👩🏻‍❤️‍💋‍👨🏾👩🏻‍❤️‍💋‍👨🏿👩🏼‍❤️‍💋‍👨🏻👩🏼‍❤️‍💋‍👨🏼👩🏼‍❤️‍💋‍👨🏽👩🏼‍❤️‍💋‍👨🏾👩🏼‍❤️‍💋‍👨🏿👩🏽‍❤️‍💋‍👨🏻👩🏽‍❤️‍💋‍👨🏼👩🏽‍❤️‍💋‍👨🏽👩🏽‍❤️‍💋‍👨🏾👩🏽‍❤️‍💋‍👨🏿👩🏾‍❤️‍💋‍👨🏻👩🏾‍❤️‍💋‍👨🏼👩🏾‍❤️‍💋‍👨🏽👩🏾‍❤️‍💋‍👨🏾👩🏾‍❤️‍💋‍👨🏿👩🏿‍❤️‍💋‍👨🏻👩🏿‍❤️‍💋‍👨🏼👩🏿‍❤️‍💋‍👨🏽👩🏿‍❤️‍💋‍👨🏾👩🏿‍❤️‍💋‍👨🏿👩‍❤️‍💋‍👩👩🏻‍❤️‍💋‍👩🏻👩🏻‍❤️‍💋‍👩🏼👩🏻‍❤️‍💋‍👩🏽👩🏻‍❤️‍💋‍👩🏾👩🏻‍❤️‍💋‍👩🏿👩🏼‍❤️‍💋‍👩🏻👩🏼‍❤️‍💋‍👩🏼👩🏼‍❤️‍💋‍👩🏽👩🏼‍❤️‍💋‍👩🏾👩🏼‍❤️‍💋‍👩🏿👩🏽‍❤️‍💋‍👩🏻👩🏽‍❤️‍💋‍👩🏼👩🏽‍❤️‍💋‍👩🏽👩🏽‍❤️‍💋‍👩🏾👩🏽‍❤️‍💋‍👩🏿👩🏾‍❤️‍💋‍👩🏻👩🏾‍❤️‍💋‍👩🏼👩🏾‍❤️‍💋‍👩🏽👩🏾‍❤️‍💋‍👩🏾👩🏾‍❤️‍💋‍👩🏿👩🏿‍❤️‍💋‍👩🏻👩🏿‍❤️‍💋‍👩🏼👩🏿‍❤️‍💋‍👩🏽👩🏿‍❤️‍💋‍👩🏾👩🏿‍❤️‍💋‍👩🏿👨‍❤️‍💋‍👨👨🏻‍❤️‍💋‍👨🏻👨🏻‍❤️‍💋‍👨🏼👨🏻‍❤️‍💋‍👨🏽👨🏻‍❤️‍💋‍👨🏾👨🏻‍❤️‍💋‍👨🏿👨🏼‍❤️‍💋‍👨🏻👨🏼‍❤️‍💋‍👨🏼👨🏼‍❤️‍💋‍👨🏽👨🏼‍❤️‍💋‍👨🏾👨🏼‍❤️‍💋‍👨🏿👨🏽‍❤️‍💋‍👨🏻👨🏽‍❤️‍💋‍👨🏼👨🏽‍❤️‍💋‍👨🏽👨🏽‍❤️‍💋‍👨🏾👨🏽‍❤️‍💋‍👨🏿👨🏾‍❤️‍💋‍👨🏻👨🏾‍❤️‍💋‍👨🏼👨🏾‍❤️‍💋‍👨🏽👨🏾‍❤️‍💋‍👨🏾👨🏾‍❤️‍💋‍👨🏿👨🏿‍❤️‍💋‍👨🏻👨🏿‍❤️‍💋‍👨🏼👨🏿‍❤️‍💋‍👨🏽👨🏿‍❤️‍💋‍👨🏾👨🏿‍❤️‍💋‍👨🏿💏💏🏻💏🏼💏🏽💏🏾💏🏿🧑🏻‍❤️‍💋‍🧑🏼🧑🏻‍❤️‍💋‍🧑🏽🧑🏻‍❤️‍💋‍🧑🏾🧑🏻‍❤️‍💋‍🧑🏿🧑🏼‍❤️‍💋‍🧑🏻🧑🏼‍❤️‍💋‍🧑🏽🧑🏼‍❤️‍💋‍🧑🏾🧑🏼‍❤️‍💋‍🧑🏿🧑🏽‍❤️‍💋‍🧑🏻🧑🏽‍❤️‍💋‍🧑🏼🧑🏽‍❤️‍💋‍🧑🏾🧑🏽‍❤️‍💋‍🧑🏿🧑🏾‍❤️‍💋‍🧑🏻🧑🏾‍❤️‍💋‍🧑🏼🧑🏾‍❤️‍💋‍🧑🏽🧑🏾‍❤️‍💋‍🧑🏿🧑🏿‍❤️‍💋‍🧑🏻🧑🏿‍❤️‍💋‍🧑🏼🧑🏿‍❤️‍💋‍🧑🏽🧑🏿‍❤️‍💋‍🧑🏾👪👨‍👩‍👦👨‍👩‍👧👨‍👩‍👧‍👦👨‍👩‍👦‍👦👨‍👩‍👧‍👧👨‍👨‍👦👨‍👨‍👧👨‍👨‍👧‍👦👨‍👨‍👦‍👦👨‍👨‍👧‍👧👩‍👩‍👦👩‍👩‍👧👩‍👩‍👧‍👦👩‍👩‍👦‍👦👩‍👩‍👧‍👧👩‍👦👩‍👧👩‍👧‍👦👩‍👦‍👦👩‍👧‍👧👨‍👦👨‍👧👨‍👧‍👦👨‍👦‍👦👨‍👧‍👧👭👩🏻‍🤝‍👩🏻👩🏻‍🤝‍👩🏼👩🏻‍🤝‍👩🏽👩🏻‍🤝‍👩🏾👩🏻‍🤝‍👩🏿👩🏼‍🤝‍👩🏻👩🏼‍🤝‍👩🏼👩🏼‍🤝‍👩🏽👩🏼‍🤝‍👩🏾👩🏼‍🤝‍👩🏿👩🏽‍🤝‍👩🏻👩🏽‍🤝‍👩🏼👩🏽‍🤝‍👩🏽👩🏽‍🤝‍👩🏾👩🏽‍🤝‍👩🏿👩🏾‍🤝‍👩🏻👩🏾‍🤝‍👩🏼👩🏾‍🤝‍👩🏽👩🏾‍🤝‍👩🏾👩🏾‍🤝‍👩🏿👩🏿‍🤝‍👩🏻👩🏿‍🤝‍👩🏼👩🏿‍🤝‍👩🏽👩🏿‍🤝‍👩🏾👩🏿‍🤝‍👩🏿👫👩🏻‍🤝‍👨🏻👩🏻‍🤝‍👨🏼👩🏻‍🤝‍👨🏽👩🏻‍🤝‍👨🏾👩🏻‍🤝‍👨🏿👩🏼‍🤝‍👨🏻👩🏼‍🤝‍👨🏼👩🏼‍🤝‍👨🏽👩🏼‍🤝‍👨🏾👩🏼‍🤝‍👨🏿👩🏽‍🤝‍👨🏻👩🏽‍🤝‍👨🏼👩🏽‍🤝‍👨🏽👩🏽‍🤝‍👨🏾👩🏽‍🤝‍👨🏿👩🏾‍🤝‍👨🏻👩🏾‍🤝‍👨🏼👩🏾‍🤝‍👨🏽👩🏾‍🤝‍👨🏾👩🏾‍🤝‍👨🏿👩🏿‍🤝‍👨🏻👩🏿‍🤝‍👨🏼👩🏿‍🤝‍👨🏽👩🏿‍🤝‍👨🏾👩🏿‍🤝‍👨🏿👬👨🏻‍🤝‍👨🏻👨🏻‍🤝‍👨🏼👨🏻‍🤝‍👨🏽👨🏻‍🤝‍👨🏾👨🏻‍🤝‍👨🏿👨🏼‍🤝‍👨🏻👨🏼‍🤝‍👨🏼👨🏼‍🤝‍👨🏽👨🏼‍🤝‍👨🏾👨🏼‍🤝‍👨🏿👨🏽‍🤝‍👨🏻👨🏽‍🤝‍👨🏼👨🏽‍🤝‍👨🏽👨🏽‍🤝‍👨🏾👨🏽‍🤝‍👨🏿👨🏾‍🤝‍👨🏻👨🏾‍🤝‍👨🏼👨🏾‍🤝‍👨🏽👨🏾‍🤝‍👨🏾👨🏾‍🤝‍👨🏿👨🏿‍🤝‍👨🏻👨🏿‍🤝‍👨🏼👨🏿‍🤝‍👨🏽👨🏿‍🤝‍👨🏾👨🏿‍🤝‍👨🏿🧑‍🤝‍🧑🧑🏻‍🤝‍🧑🏻🧑🏻‍🤝‍🧑🏼🧑🏻‍🤝‍🧑🏽🧑🏻‍🤝‍🧑🏾🧑🏻‍🤝‍🧑🏿🧑🏼‍🤝‍🧑🏻🧑🏼‍🤝‍🧑🏼🧑🏼‍🤝‍🧑🏽🧑🏼‍🤝‍🧑🏾🧑🏼‍🤝‍🧑🏿🧑🏽‍🤝‍🧑🏻🧑🏽‍🤝‍🧑🏼🧑🏽‍🤝‍🧑🏽🧑🏽‍🤝‍🧑🏾🧑🏽‍🤝‍🧑🏿🧑🏾‍🤝‍🧑🏻🧑🏾‍🤝‍🧑🏼🧑🏾‍🤝‍🧑🏽🧑🏾‍🤝‍🧑🏾🧑🏾‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏻🧑🏿‍🤝‍🧑🏼🧑🏿‍🤝‍🧑🏽🧑🏿‍🤝‍🧑🏾🧑

사물
🎈🎆🎇🧨✨🎉🎎🎍🎋🎄🎃🎊🎏🎐🎑🧧🎀🎁🎡🎠🎫🎟️🎞️🎗️🎢🎪🎭🖼️🎨🧵🕶️👓🛒🪢🧶🪡🦺🥽🥼🧥👔👕👗🧦🧤🧣🩳👖🥻👘👚🩲🩱👙🩴🎒🛍️👝👜👛👞👟🥾🥿👠👡⛑️🪖🧢👑🩰👢👒🎩🎓💋💄💍🏐🏀🥎⚾⚽💎🏈🏉🎱🎳🥌⛳🎿🛶🎽🤿🎣⛸️🛷🥅🏒🥍🏏🏑🎯🪁🥏🎾🏸🏓🥊🥋🥇🥈🥉🏅🎲🎰🕹️🎮🏆🎖️🔮🪄🧿🧩🧸🪅♟️🀄🃏🎴🪀🪆♠️♣️♥️♦️🔈🔉🎵🎼🔔📣📢🔊🏿‍🤝‍🧑🏿

특수문자가 많은 곳들

비록 우분투 리눅스에 특수문자 입력기는 없지만
다양한 특수문자를 제공하는 사이트에서 복사해서 쓰면 됩니다.






특이한 특수문자 이모티콘 텍대 모음 | ⌨️SNS Keyboard
SNS와 채팅에 활용할 수 있는 다양한 특수문자 이모티콘 목록을 제공하는 온라인 도구입니다.









GitHub Pages 특수문자

GitHub Pages에서 사용할 수 있는 다양한 이모티콘들이 존재한다.
아래 홈페이지에 접속하면 다양한 이모지들을 살펴볼 수 있다.






Complete list of github markdown emoji markup
Complete list of github markdown emoji markup. GitHub Gist: instantly share code, notes, and snippets.









다양한 무료 아이콘

https://ionic.io/ionicons

이상입니다.
["윈도우즈는 특수문자 천국\n\n윈도우즈 운영체제에서는 \u{1FA9F} + . 단축키로 \n다양한 특수문자들을 입력할 수 있습니다.\n\n우분투 리눅스는 특수 문자 입력 어려움\n\n반면, 우분투 리눅스에서는 특수 문자 입력기가 없습니다. \n이 때문에 특수문자 입력이 어렵습니다.\n\n인기 특수 문자들\n\n인기있는 특수문자들을 기록해둡니다.\n\n\n 🐍 : 파이썬, 뱀\n 👍 : 엄지척\n 😺 : 고양이\n 🙏 : 기도\n ❌ : 가위표\n ⭕ : 공표\n 🚫 : 금지\n 🆗 : OK\n 🆖 : NG\n 🔼 : 위로\n 🔽 : 아래로\n ▶️ : 오른쪽으로\n ◀️ : 왼쪽으로\n ⬅️ : 왼쪽 화살표\n ➡️ : 오른쪽 화살표\n ⬆️ : 위쪽 화살표\n ⬇️ : 아래쪽 화살표\n ✔️ : 체크 표시\n ✅ : 체크 표시\n ✍️ : 글을 쓰고 있는 손, 편집 버튼\n ✏️ : 연필, 편집 버튼\n #️⃣ : #, sharp, 샵, 우물정\n \u{1FA9F} : 윈도우, 윈도우즈, 창문\n 🌐 : 웹브라우저\n Ⓜ️ : 이메일, e-mail\n 📧 : 이메일, e-mail\n 📑 : 목록, 인덱스, 목차\n\n\n표정\n😀😁😂🤣😃😄😅😆😉😊😋😎😍😘🥰😗😙\u{1F972}😚☺️🙂🤗🤩🤔🤨😐😑😶😶‍🌫️🙄😏😣😥😮🤐😯😪😫🥱😴😌😛😜😝🤤😒😓😔😕🙃🤑😲☹️🙁😖😞😟😤😢😭😦😧😨😩🤯😬😮‍💨😰😱🥵🥶😳🤪😵😵‍💫🥴😠😡🤬😷🤒🤕🤢🤮🤧😇🥳\u{1F978}🥺🤠🤡🤥🤫🤭🧐🤓😈👿👹👺💀☠️👻👽👾🤖💩\n\n동물\n😺😸😹😻😼😽🙀😿😾🙈🙉🙊🐵🐶🐺🐱🦁🐯🦒🦊🦝🐮🐷🐗🐭🐹🐰🐻🐻‍❄️🐨🐼🐸🦓🐴🦄🐔🐲🐽🐾🐒🦍🦧🦮🐕‍🦺🐩🐕🐈🐈‍⬛🐅🐆🐎🦌\u{1F9AC}🦏🦛🐂🐃🐄🐖🐏🐑🐐🐪🐫🦙🦘🦥🦨🦡🐘\u{1F9A3}🐁🐀🦔🐇🐿️\u{1F9AB}🦎🐊🐢🐍🐉🦕🦖🦦🦈🐬\u{1F9AD}🐳🐋🐟🐠🐡🦐🦑🐙🦞🦀🐚🦆🐓🦃🦅🕊️🦢🦜🦩🦚🦉\u{1F9A4}\u{1FAB6}🐦🐧🐥🐤🐣🦇🦋🐌🐛🦟\u{1FAB0}\u{1FAB1}🦗🐜\u{1FAB3}🐝\u{1FAB2}🐞🦂🕷️🕸️🦠\n\n괴물\n🧞‍♀️🧞‍♂️🧞🧟‍♀️🧟‍♂️🧟🗣️👤👥\u{1FAC2}\n\n신체\n👁️👀🦴🦷👅👄🧠\u{1FAC0}\u{1FAC1}🦾🦿👣\n\n활동\n🤺⛷️🤼‍♀️🤼‍♂️🤼👯‍♀️👯‍♂️👯\n\n관계\n👩‍❤️‍👨👩🏻‍❤️‍👨🏻👩🏻‍❤️‍👨🏼👩🏻‍❤️‍👨🏽👩🏻‍❤️‍👨🏾👩🏻‍❤️‍👨🏿👩🏼‍❤️‍👨🏻👩🏼‍❤️‍👨🏼👩🏼‍❤️‍👨🏽👩🏼‍❤️‍👨🏾👩🏼‍❤️‍👨🏿👩🏽‍❤️‍👨🏻👩🏽‍❤️‍👨🏼👩🏽‍❤️‍👨🏽👩🏽‍❤️‍👨🏾👩🏽‍❤️‍👨🏿👩🏾‍❤️‍👨🏻👩🏾‍❤️‍👨🏼👩🏻👨🏻🧑🏻🧑🏻👧🏻👧🏻👦🏻🧒🏻👨🏻‍🦰🧓🏻👵🏻👵🏻🧑🏻‍🦰🧑🏻‍🦱👩🏻‍🦲👨🏻‍🦲👱🏻‍♂️👱🏻‍♀️🧑🏻‍🦳👨🏻‍🦳👩🏾‍❤️‍👨🏽👩🏾‍❤️‍👨🏾👩🏾‍❤️‍👨🏿👩🏿‍❤️‍👨🏻👩🏿‍❤️‍👨🏼👩🏿‍❤️‍👨🏽👩🏿‍❤️‍👨🏾👩🏿‍❤️‍👨🏿👩‍❤️‍👩👩🏻‍❤️‍👩🏻👩🏻‍❤️‍👩🏼👩🏻‍❤️‍👩🏽👩🏻‍❤️‍👩🏾👩🏻‍❤️‍👩🏿👩🏼‍❤️‍👩🏻👩🏼‍❤️‍👩🏼👩🏼‍❤️‍👩🏽👩🏼‍❤️‍👩🏾👩🏼‍❤️‍👩🏿👩🏽‍❤️‍👩🏻👩🏽‍❤️‍👩🏼👩🏽‍❤️‍👩🏽👩🏽‍❤️‍👩🏾👩🏽‍❤️‍👩🏿👩🏾‍❤️‍👩🏻👩🏾‍❤️‍👩🏼👩🏾‍❤️‍👩🏽👩🏾‍❤️‍👩🏾👩🏾‍❤️‍👩🏿👩🏿‍❤️‍👩🏻👩🏿‍❤️‍👩🏼👩🏿‍❤️‍👩🏽👩🏿‍❤️‍👩🏾👩🏿‍❤️‍👩🏿👨‍❤️‍👨👨🏻‍❤️‍👨🏻👨🏻‍❤️‍👨🏼👨🏻‍❤️‍👨🏽👨🏻‍❤️‍👨🏾👨🏻‍❤️‍👨🏿👨🏼‍❤️‍👨🏻👨🏼‍❤️‍👨🏼👨🏼‍❤️‍👨🏽👨🏼‍❤️‍👨🏾👨🏼‍❤️‍👨🏿👨🏽‍❤️‍👨🏻👨🏽‍❤️‍👨🏼👨🏽‍❤️‍👨🏽👨🏽‍❤️‍👨🏾👨🏽‍❤️‍👨🏿👨🏾‍❤️‍👨🏻👨🏾‍❤️‍👨🏼👨🏾‍❤️‍👨🏽👨🏾‍❤️‍👨🏾👨🏾‍❤️‍👨🏿👨🏿‍❤️‍👨🏻👨🏿‍❤️‍👨🏼👨🏿‍❤️‍👨🏽👨🏿‍❤️‍👨🏾👨🏿‍❤️‍👨🏿💑💑🏻💑🏼💑🏽💑🏾💑🏿🧑🏻‍❤️‍🧑🏼🧑🏻‍❤️‍🧑🏽🧑🏻‍❤️‍🧑🏾🧑🏻‍❤️‍🧑🏿🧑🏼‍❤️‍🧑🏻🧑🏼‍❤️‍🧑🏽🧑🏼‍❤️‍🧑🏾🧑🏼‍❤️‍🧑🏿🧑🏽‍❤️‍🧑🏻🧑🏽‍❤️‍🧑🏼🧑🏽‍❤️‍🧑🏾🧑🏽‍❤️‍🧑🏿🧑🏾‍❤️‍🧑🏻🧑🏾‍❤️‍🧑🏼🧑🏾‍❤️‍🧑🏽🧑🏾‍❤️‍🧑🏿🧑🏿‍❤️‍🧑🏻🧑🏿‍❤️‍🧑🏼🧑🏿‍❤️‍🧑🏽🧑🏿‍❤️‍🧑🏾👩‍❤️‍💋‍👨👩🏻‍❤️‍💋‍👨🏻👩🏻‍❤️‍💋‍👨🏼👩🏻‍❤️‍💋‍👨🏽👩🏻‍❤️‍💋‍👨🏾👩🏻‍❤️‍💋‍👨🏿👩🏼‍❤️‍💋‍👨🏻👩🏼‍❤️‍💋‍👨🏼👩🏼‍❤️‍💋‍👨🏽👩🏼‍❤️‍💋‍👨🏾👩🏼‍❤️‍💋‍👨🏿👩🏽‍❤️‍💋‍👨🏻👩🏽‍❤️‍💋‍👨🏼👩🏽‍❤️‍💋‍👨🏽👩🏽‍❤️‍💋‍👨🏾👩🏽‍❤️‍💋‍👨🏿👩🏾‍❤️‍💋‍👨🏻👩🏾‍❤️‍💋‍👨🏼👩🏾‍❤️‍💋‍👨🏽👩🏾‍❤️‍💋‍👨🏾👩🏾‍❤️‍💋‍👨🏿👩🏿‍❤️‍💋‍👨🏻👩🏿‍❤️‍💋‍👨🏼👩🏿‍❤️‍💋‍👨🏽👩🏿‍❤️‍💋‍👨🏾👩🏿‍❤️‍💋‍👨🏿👩‍❤️‍💋‍👩👩🏻‍❤️‍💋‍👩🏻👩🏻‍❤️‍💋‍👩🏼👩🏻‍❤️‍💋‍👩🏽👩🏻‍❤️‍💋‍👩🏾👩🏻‍❤️‍💋‍👩🏿👩🏼‍❤️‍💋‍👩🏻👩🏼‍❤️‍💋‍👩🏼👩🏼‍❤️‍💋‍👩🏽👩🏼‍❤️‍💋‍👩🏾👩🏼‍❤️‍💋‍👩🏿👩🏽‍❤️‍💋‍👩🏻👩🏽‍❤️‍💋‍👩🏼👩🏽‍❤️‍💋‍👩🏽👩🏽‍❤️‍💋‍👩🏾👩🏽‍❤️‍💋‍👩🏿👩🏾‍❤️‍💋‍👩🏻👩🏾‍❤️‍💋‍👩🏼👩🏾‍❤️‍💋‍👩🏽👩🏾‍❤️‍💋‍👩🏾👩🏾‍❤️‍💋‍👩🏿👩🏿‍❤️‍💋‍👩🏻👩🏿‍❤️‍💋‍👩🏼👩🏿‍❤️‍💋‍👩🏽👩🏿‍❤️‍💋‍👩🏾👩🏿‍❤️‍💋‍👩🏿👨‍❤️‍💋‍👨👨🏻‍❤️‍💋‍👨🏻👨🏻‍❤️‍💋‍👨🏼👨🏻‍❤️‍💋‍👨🏽👨🏻‍❤️‍💋‍👨🏾👨🏻‍❤️‍💋‍👨🏿👨🏼‍❤️‍💋‍👨🏻👨🏼‍❤️‍💋‍👨🏼👨🏼‍❤️‍💋‍👨🏽👨🏼‍❤️‍💋‍👨🏾👨🏼‍❤️‍💋‍👨🏿👨🏽‍❤️‍💋‍👨🏻👨🏽‍❤️‍💋‍👨🏼👨🏽‍❤️‍💋‍👨🏽👨🏽‍❤️‍💋‍👨🏾👨🏽‍❤️‍💋‍👨🏿👨🏾‍❤️‍💋‍👨🏻👨🏾‍❤️‍💋‍👨🏼👨🏾‍❤️‍💋‍👨🏽👨🏾‍❤️‍💋‍👨🏾👨🏾‍❤️‍💋‍👨🏿👨🏿‍❤️‍💋‍👨🏻👨🏿‍❤️‍💋‍👨🏼👨🏿‍❤️‍💋‍👨🏽👨🏿‍❤️‍💋‍👨🏾👨🏿‍❤️‍💋‍👨🏿💏💏🏻💏🏼💏🏽💏🏾💏🏿🧑🏻‍❤️‍💋‍🧑🏼🧑🏻‍❤️‍💋‍🧑🏽🧑🏻‍❤️‍💋‍🧑🏾🧑🏻‍❤️‍💋‍🧑🏿🧑🏼‍❤️‍💋‍🧑🏻🧑🏼‍❤️‍💋‍🧑🏽🧑🏼‍❤️‍💋‍🧑🏾🧑🏼‍❤️‍💋‍🧑🏿🧑🏽‍❤️‍💋‍🧑🏻🧑🏽‍❤️‍💋‍🧑🏼🧑🏽‍❤️‍💋‍🧑🏾🧑🏽‍❤️‍💋‍🧑🏿🧑🏾‍❤️‍💋‍🧑🏻🧑🏾‍❤️‍💋‍🧑🏼🧑🏾‍❤️‍💋‍🧑🏽🧑🏾‍❤️‍💋‍🧑🏿🧑🏿‍❤️‍💋‍🧑🏻🧑🏿‍❤️‍💋‍🧑🏼🧑🏿‍❤️‍💋‍🧑🏽🧑🏿‍❤️‍💋‍🧑🏾👪👨‍👩‍👦👨‍👩‍👧👨‍👩‍👧‍👦👨‍👩‍👦‍👦👨‍👩‍👧‍👧👨‍👨‍👦👨‍👨‍👧👨‍👨‍👧‍👦👨‍👨‍👦‍👦👨‍👨‍👧‍👧👩‍👩‍👦👩‍👩‍👧👩‍👩‍👧‍👦👩‍👩‍👦‍👦👩‍👩‍👧‍👧👩‍👦👩‍👧👩‍👧‍👦👩‍👦‍👦👩‍👧‍👧👨‍👦👨‍👧👨‍👧‍👦👨‍👦‍👦👨‍👧‍👧👭👩🏻‍🤝‍👩🏻👩🏻‍🤝‍👩🏼👩🏻‍🤝‍👩🏽👩🏻‍🤝‍👩🏾👩🏻‍🤝‍👩🏿👩🏼‍🤝‍👩🏻👩🏼‍🤝‍👩🏼👩🏼‍🤝‍👩🏽👩🏼‍🤝‍👩🏾👩🏼‍🤝‍👩🏿👩🏽‍🤝‍👩🏻👩🏽‍🤝‍👩🏼👩🏽‍🤝‍👩🏽👩🏽‍🤝‍👩🏾👩🏽‍🤝‍👩🏿👩🏾‍🤝‍👩🏻👩🏾‍🤝‍👩🏼👩🏾‍🤝‍👩🏽👩🏾‍🤝‍👩🏾👩🏾‍🤝‍👩🏿👩🏿‍🤝‍👩🏻👩🏿‍🤝‍👩🏼👩🏿‍🤝‍👩🏽👩🏿‍🤝‍👩🏾👩🏿‍🤝‍👩🏿👫👩🏻‍🤝‍👨🏻👩🏻‍🤝‍👨🏼👩🏻‍🤝‍👨🏽👩🏻‍🤝‍👨🏾👩🏻‍🤝‍👨🏿👩🏼‍🤝‍👨🏻👩🏼‍🤝‍👨🏼👩🏼‍🤝‍👨🏽👩🏼‍🤝‍👨🏾👩🏼‍🤝‍👨🏿👩🏽‍🤝‍👨🏻👩🏽‍🤝‍👨🏼👩🏽‍🤝‍👨🏽👩🏽‍🤝‍👨🏾👩🏽‍🤝‍👨🏿👩🏾‍🤝‍👨🏻👩🏾‍🤝‍👨🏼👩🏾‍🤝‍👨🏽👩🏾‍🤝‍👨🏾👩🏾‍🤝‍👨🏿👩🏿‍🤝‍👨🏻👩🏿‍🤝‍👨🏼👩🏿‍🤝‍👨🏽👩🏿‍🤝‍👨🏾👩🏿‍🤝‍👨🏿👬👨🏻‍🤝‍👨🏻👨🏻‍🤝‍👨🏼👨🏻‍🤝‍👨🏽👨🏻‍🤝‍👨🏾👨🏻‍🤝‍👨🏿👨🏼‍🤝‍👨🏻👨🏼‍🤝‍👨🏼👨🏼‍🤝‍👨🏽👨🏼‍🤝‍👨🏾👨🏼‍🤝‍👨🏿👨🏽‍🤝‍👨🏻👨🏽‍🤝‍👨🏼👨🏽‍🤝‍👨🏽👨🏽‍🤝‍👨🏾👨🏽‍🤝‍👨🏿👨🏾‍🤝‍👨🏻👨🏾‍🤝‍👨🏼👨🏾‍🤝‍👨🏽👨🏾‍🤝‍👨🏾👨🏾‍🤝‍👨🏿👨🏿‍🤝‍👨🏻👨🏿‍🤝‍👨🏼👨🏿‍🤝‍👨🏽👨🏿‍🤝‍👨🏾👨🏿‍🤝‍👨🏿🧑‍🤝‍🧑🧑🏻‍🤝‍🧑🏻🧑🏻‍🤝‍🧑🏼🧑🏻‍🤝‍🧑🏽🧑🏻‍🤝‍🧑🏾🧑🏻‍🤝‍🧑🏿🧑🏼‍🤝‍🧑🏻🧑🏼‍🤝‍🧑🏼🧑🏼‍🤝‍🧑🏽🧑🏼‍🤝‍🧑🏾🧑🏼‍🤝‍🧑🏿🧑🏽‍🤝‍🧑🏻🧑🏽‍🤝‍🧑🏼🧑🏽‍🤝‍🧑🏽🧑🏽‍🤝‍🧑🏾🧑🏽‍🤝‍🧑🏿🧑🏾‍🤝‍🧑🏻🧑🏾‍🤝‍🧑🏼🧑🏾‍🤝‍🧑🏽🧑🏾‍🤝‍🧑🏾🧑🏾‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏻🧑🏿‍🤝‍🧑🏼🧑🏿‍🤝‍🧑🏽🧑🏿‍🤝‍🧑🏾🧑\n\n사물\n🎈🎆🎇🧨✨🎉🎎🎍🎋🎄🎃🎊🎏🎐🎑🧧🎀🎁🎡🎠🎫🎟️🎞️🎗️🎢🎪🎭🖼️🎨🧵🕶️👓🛒\u{1FAA2}🧶\u{1FAA1}🦺🥽🥼🧥👔👕👗🧦🧤🧣🩳👖🥻👘👚🩲🩱👙\u{1FA74}🎒🛍️👝👜👛👞👟🥾🥿👠👡⛑️\u{1FA96}🧢👑🩰👢👒🎩🎓💋💄💍🏐🏀🥎⚾⚽💎🏈🏉🎱🎳🥌⛳🎿🛶🎽🤿🎣⛸️🛷🥅🏒🥍🏏🏑🎯🪁🥏🎾🏸🏓🥊🥋🥇🥈🥉🏅🎲🎰🕹️🎮🏆🎖️🔮\u{1FA84}🧿🧩🧸\u{1FA85}♟️🀄🃏🎴🪀\u{1FA86}♠️♣️♥️♦️🔈🔉🎵🎼🔔📣📢🔊🏿‍🤝‍🧑🏿\n\n특수문자가 많은 곳들\n\n비록 우분투 리눅스에 특수문자 입력기는 없지만 \n다양한 특수문자를 제공하는 사이트에서 복사해서 쓰면 됩니다.\n\n\n\n\n \n \n 특이한 특수문자 이모티콘 텍대 모음 | ⌨️SNS Keyboard\n SNS와 채팅에 활용할 수 있는 다양한 특수문자 이모티콘 목록을 제공하는 온라인 도구입니다.\n \n \n \n \n \n \n\n\n\nGitHub Pages 특수문자\n\nGitHub Pages에서 사용할 수 있는 다양한 이모티콘들이 존재한다. \n아래 홈페이지에 접속하면 다양한 이모지들을 살펴볼 수 있다.\n\n\n\n\n \n \n Complete list of github markdown emoji markup\n Complete list of github markdown emoji markup. GitHub Gist: instantly share code, notes, and snippets.\n \n \n \n \n \n \n\n\n\n다양한 무료 아이콘\n\nhttps://ionic.io/ionicons\n\n이상입니다.\n"]
Title : 링크 프리뷰 구현하는 방법(float 스타일 사용)
URL : /html/html-horizontal-objects-with-float-style.html
Description : 티스토리 블로그에 다른 게시물 링크의 이미지 및 내용이 미리 표시되는 것처럼 프리뷰를 구현하는 방법 설명
Content : 티스토리 링크 프리뷰

티스토리 블로그에 다른 게시물 링크를 걸게 되면,
위의 그림처럼 대표 이미지와 내용이 미리 표시된다.
GitHub Pages로도 이와 유사한 기능을 사용할 수 있다.

예제

<div style="height: 300; border: 1px dashed; border-radius: 3px;">
<div style="width: 20%; float: left; margin: 2px; height: 100%">
<img style="border-radius: 20px;" src="/assets/logo.png" width=100%>
</div>

<div style="float: right; margin: 10px 0 10px 0; width: 75%; height: 100%">
<h3>VS Code 단축키 설명</h3>
소스코드 편집 스킬을 향상시켜줄 단축키들 설명<br>
(2022-10-24 작성)<br>
<a href="/vscode/vs-code-shortcuts.html">더보기</a>
</div>

<div style="clear: both; width: 0">
</div>
</div>



여러 종류의 객체를 가로로 나란히 출력하기 위해서는 float: left; 테그를 사용하면 된다.
해당 속성을 해제하기 위해서는 clear: both; 구문을 입력하면 된다.


["티스토리 링크 프리뷰\n\n티스토리 블로그에 다른 게시물 링크를 걸게 되면, \n위의 그림처럼 대표 이미지와 내용이 미리 표시된다.\nGitHub Pages로도 이와 유사한 기능을 사용할 수 있다.\n\n예제\n\n<div style=\"height: 300; border: 1px dashed; border-radius: 3px;\">\n <div style=\"width: 20%; float: left; margin: 2px; height: 100%\">\n <img style=\"border-radius: 20px;\" src=\"/assets/logo.png\" width=100%>\n </div>\n\n <div style=\"float: right; margin: 10px 0 10px 0; width: 75%; height: 100%\">\n <h3>VS Code 단축키 설명</h3>\n 소스코드 편집 스킬을 향상시켜줄 단축키들 설명<br>\n (2022-10-24 작성)<br>\n <a href=\"/vscode/vs-code-shortcuts.html\">더보기</a>\n </div>\n\n <div style=\"clear: both; width: 0\">\n </div>\n</div>\n\n\n\n 여러 종류의 객체를 가로로 나란히 출력하기 위해서는 float: left; 테그를 사용하면 된다.\n해당 속성을 해제하기 위해서는 clear: both; 구문을 입력하면 된다.\n\n\n"]
Title : 우분투 리눅스에 Visual Studio Code 설치하는 방법
URL : /vscode/how-to-install-vscode.html
Description : 우분투 리눅스에 Visual Studio Code 설치하는 방법
Content : Visual Studio Code 소개

SW 개발자로 약 15년동안 업무를 수행해왔습니다.
그동안 가장 많이 사용했던 소스 코드 편집기는 Source Insight 였습니다.
Source Insight는 유료인데다가 리눅스에서는 사용이 불가합니다.

Visual Studio Code는 윈도우즈와 리눅스 모두에서 사용이 가능합니다.
무료로 사용할 수 있고, 다양한 확장 기능도 제공합니다.


윈도우즈와 리눅스 모두에서 사용이 가능하다.
무료로 사용할 수 있다.
다양한 확장 기능을 제공한다.


Visual Studio Code 다운로드

Visual Studio Code






Visual Studio Code - Code Editing. Redefined
Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.









위의 경로로 접속하시면 Visual Studio Code를 무료로 다운로드 가능합니다.

Visual Studio Code 설치 방법

다운로드가 완료되면 아래 명령으로 설치합니다.

$ sudo dpkg -i code_1.72.2-1665614327_amd64.deb


["Visual Studio Code 소개\n\nSW 개발자로 약 15년동안 업무를 수행해왔습니다. \n그동안 가장 많이 사용했던 소스 코드 편집기는 Source Insight 였습니다. \nSource Insight는 유료인데다가 리눅스에서는 사용이 불가합니다.\n\nVisual Studio Code는 윈도우즈와 리눅스 모두에서 사용이 가능합니다. \n무료로 사용할 수 있고, 다양한 확장 기능도 제공합니다.\n\n\n 윈도우즈와 리눅스 모두에서 사용이 가능하다.\n 무료로 사용할 수 있다.\n 다양한 확장 기능을 제공한다.\n\n\nVisual Studio Code 다운로드\n\nVisual Studio Code\n\n\n\n\n \n \n Visual Studio Code - Code Editing. Redefined\n Visual Studio Code is a code editor redefined and optimized for building and debugging modern web and cloud applications.  Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.\n \n \n \n \n \n \n\n\n\n위의 경로로 접속하시면 Visual Studio Code를 무료로 다운로드 가능합니다.\n\nVisual Studio Code 설치 방법\n\n다운로드가 완료되면 아래 명령으로 설치합니다.\n\n$ sudo dpkg -i code_1.72.2-1665614327_amd64.deb\n\n\n"]
Title : 코스트코 현대카드 발급 및 맥스봉 가격 비교
URL : /diary/2022/10/22/%EC%BD%94%EC%8A%A4%ED%8A%B8%EC%BD%94-%ED%98%84%EB%8C%80%EC%B9%B4%EB%93%9C-%EB%B0%9C%EA%B8%89.html
Description : Costco에서 Hyundai Card를 발급받았다. 쇼핑을 하면서 살펴본 맥스봉 가격을 비교해본다.
Content : 요약

코스트코에서 현금으로만 결제하다가, 드디어 현대카드를 발급했습니다.
코스트코에서 구입한 맥스봉의 가격을 군마트와 비교해봅니다.

현대카드 발급

코스트코 양재점 1층에서 코스트코 현대카드를 발급 받았습니다.
현장에서 바로 모바일 카드로 발급받아서 삼성페이로 사용했습니다.
실물카드는 추후에 집으로 수령했습니다.

며칠 후 실물카드 배송원분으로부터 연락이 왔습니다.
말길을 잘 이해하지 못하고 정신이 없으신 분이었습니다.
제 이름을 제대로 알아듣지 못해서 다섯 번은 반복해서 이야기했던 것 같네요.

맥스봉 가격 비교


얼마전에 편의점에서 맥스봉을 구입하고 감짝 놀랐습니다.
맥스봉 1개의 가격이 2천원대였기 때문입니다.
그 이후에 군마트에서 동일한 상품을 구입했는데 훨씬 저렴했습니다.




상품
가격
개당 가격
10g당 가격
구입처
비고




55g X 16
7,680원
480원
87원
군마트
낱개 구입 가능


40g X 27
10,290원
381원
95원
코스트코
박스로만 구입 가능




맥스봉 치즈 플러스의 가격을 비교했습니다.
코스트코나 군마트에서 판매하는 맥스봉 가격을 따져보면, 1개당 400원 ~ 500원 정도입니다.
10g 당 가격을 살펴보면 군마트가 87원으로 가장 저렴합니다.
낱개로 구입 가능하면서도 가장 저렴하게 구입할 수 있다니 놀라울 따름입니다.

["요약\n\n코스트코에서 현금으로만 결제하다가, 드디어 현대카드를 발급했습니다. \n코스트코에서 구입한 맥스봉의 가격을 군마트와 비교해봅니다.\n\n현대카드 발급\n\n코스트코 양재점 1층에서 코스트코 현대카드를 발급 받았습니다. \n현장에서 바로 모바일 카드로 발급받아서 삼성페이로 사용했습니다. \n실물카드는 추후에 집으로 수령했습니다.\n\n며칠 후 실물카드 배송원분으로부터 연락이 왔습니다. \n말길을 잘 이해하지 못하고 정신이 없으신 분이었습니다. \n제 이름을 제대로 알아듣지 못해서 다섯 번은 반복해서 이야기했던 것 같네요.\n\n맥스봉 가격 비교\n\n\n얼마전에 편의점에서 맥스봉을 구입하고 감짝 놀랐습니다. \n맥스봉 1개의 가격이 2천원대였기 때문입니다. \n그 이후에 군마트에서 동일한 상품을 구입했는데 훨씬 저렴했습니다.\n\n\n \n \n 상품\n 가격\n 개당 가격\n 10g당 가격\n 구입처\n 비고\n \n \n \n \n 55g X 16\n 7,680원\n 480원\n 87원\n 군마트\n 낱개 구입 가능\n \n \n 40g X 27\n 10,290원\n 381원\n 95원\n 코스트코\n 박스로만 구입 가능\n \n \n\n\n맥스봉 치즈 플러스의 가격을 비교했습니다. \n코스트코나 군마트에서 판매하는 맥스봉 가격을 따져보면, 1개당 400원 ~ 500원 정도입니다. \n10g 당 가격을 살펴보면 군마트가 87원으로 가장 저렴합니다. \n낱개로 구입 가능하면서도 가장 저렴하게 구입할 수 있다니 놀라울 따름입니다.\n\n"]
Title : 회사는 나에게 모든 것을 해줬다. 나만 잘하면 된다.
URL : /diary/2022/10/21/%ED%9A%8C%EC%82%AC%ED%97%AC%EC%93%B0%EC%9E%A5.html
Description : 회사 피트니스를 처음 이용해본 감격을 기록합니다.
Content : 회사 피트니스 센터에서 갑자기 연락이 왔다.
이번달에 회사 휘트니스 센터에 등록이 되었는데,
그동안 운동을 한 번도 하지 않았다는 내용이었다.
한 달에 30분 이상 운동을 3번 이상 하지 않으면
피트니스 등록이 해제된다는 독려 메일이었다.

그럴리가?
지난달에 피트니스를 신청하기를 했지만,
등록이 되었다는 이야기는 전혀 듣지 못했다.
물어보니 메일로 연락을 했었을 것이란다.
메일함을 뒤져봤지만 피트니스 센터에 등록되었다는 메일은 없었다.



처음으로 방문한 헬쓰장은 어떻게 이용해야 되는지 알기 어려웠다.
사원증을 찍었더니 헬쓰장 문이 열리긴 했는데,
탈의실 락커를 어떻게 사용해야되는지 알기 어려웠다.

탈의실에서 주섬주섬 망설이고 있는데,
피트니스를 관리하는 여직원이 남자 샤워장에서
타월을 수거하면서 나오는 것이었다.

남자 탈의실 앞에 여직원 타월 수거 시간이 적혀 있었는데,
분명 그 시간은 아니었다.
다행히 탈의실을 이용하는 방법을 몰랐기에 다행이다.

탈의실 이용 방법을 물어봐서 설명을 들었다.
사원증을 찍으면 락커 번호가 나온다고 하는데,
내 사원증은 찍었더니 미등록 카드라고 나왔다.
직원분께서 내 카드를 등록해주셨다.



일단은 임시로 락커를 할당해주셨다.
그 다음주 월요일에 다시 갔는데 여전히 내 사원증은 등록되어 있지 않았다.
회원 등록 여부를 알려주는 것부터, 사원증 등록,
린넨 수거 등의 업무가 뭔가 매끄럽지 못했던 것 같다.

그래도 아무튼 즐겁게 운동할 수 있어서 좋았다.

회사는 나에게 월급도 주고, 점심밥도 주고, 피트니스도 제공해줬다.
회사에서 나에게 해야 할 것들은 모두 다 해줬다.
나머지는 나만 잘 하면 된다.


운동 기록




일시
운동 내용
운동 시간
비고




2022-10-21
싸이클 + 다리운동
약 30분
 


2022-10-24
쓰레드밀
약 30분
 




앞으로도 열심히 운동해야 되겠다.
["회사 피트니스 센터에서 갑자기 연락이 왔다. \n이번달에 회사 휘트니스 센터에 등록이 되었는데, \n그동안 운동을 한 번도 하지 않았다는 내용이었다. \n한 달에 30분 이상 운동을 3번 이상 하지 않으면 \n피트니스 등록이 해제된다는 독려 메일이었다.\n\n그럴리가? \n지난달에 피트니스를 신청하기를 했지만, \n등록이 되었다는 이야기는 전혀 듣지 못했다. \n물어보니 메일로 연락을 했었을 것이란다. \n메일함을 뒤져봤지만 피트니스 센터에 등록되었다는 메일은 없었다.\n\n\n\n처음으로 방문한 헬쓰장은 어떻게 이용해야 되는지 알기 어려웠다. \n사원증을 찍었더니 헬쓰장 문이 열리긴 했는데, \n탈의실 락커를 어떻게 사용해야되는지 알기 어려웠다.\n\n탈의실에서 주섬주섬 망설이고 있는데, \n피트니스를 관리하는 여직원이 남자 샤워장에서 \n타월을 수거하면서 나오는 것이었다.\n\n남자 탈의실 앞에 여직원 타월 수거 시간이 적혀 있었는데, \n분명 그 시간은 아니었다. \n다행히 탈의실을 이용하는 방법을 몰랐기에 다행이다.\n\n탈의실 이용 방법을 물어봐서 설명을 들었다. \n사원증을 찍으면 락커 번호가 나온다고 하는데, \n내 사원증은 찍었더니 미등록 카드라고 나왔다. \n직원분께서 내 카드를 등록해주셨다.\n\n\n\n일단은 임시로 락커를 할당해주셨다. \n그 다음주 월요일에 다시 갔는데 여전히 내 사원증은 등록되어 있지 않았다. \n회원 등록 여부를 알려주는 것부터, 사원증 등록, \n린넨 수거 등의 업무가 뭔가 매끄럽지 못했던 것 같다.\n\n그래도 아무튼 즐겁게 운동할 수 있어서 좋았다.\n\n 회사는 나에게 월급도 주고, 점심밥도 주고, 피트니스도 제공해줬다. \n회사에서 나에게 해야 할 것들은 모두 다 해줬다. \n나머지는 나만 잘 하면 된다.\n\n\n운동 기록\n\n\n \n \n 일시\n 운동 내용\n 운동 시간\n 비고\n \n \n \n \n 2022-10-21\n 싸이클 + 다리운동\n 약 30분\n  \n \n \n 2022-10-24\n 쓰레드밀\n 약 30분\n  \n \n \n\n\n앞으로도 열심히 운동해야 되겠다.\n"]
Title : 스팸 전화번호 총정리
URL : /_pages/security/2022-10-17-스팸전화번호총정리.html
Description : 성가신 스팸 전화번호를 기록해두고자 합니다.
Content : 스팸 전화번호




전화번호
업체
비고




070-4578-1711
오케이 금융 대출
대출 광고


070-4518-2735
오케이 금융 대출
광고


1670-0283
오케이 금융 대출
광고


02-6238-0730
여론조사기관
보험 관련


070-8977-3754
SK 기변센터
스마트폰 광고


02-6475-4650
보험점검센터
OK캐시백


02-2162-7404
투자금액지원
광고


02-6975-9391
주식자금대출
광고




스팸이 아닌 전화번호




전화번호
업체
비고




02-1877-8462
흥국화재 이유다이렉트
자동차 보험 가입 안내


1688-1688
흥국화재 이유다이렉트
자동차 보험 가입 관련


02-323-1127
ROTC 중앙회
직장 확인 및 자택 주소 확인


02-1661-0544
유플러스 알뜰 모바일
알뜰요금제 개통 상담



["스팸 전화번호\n\n\n \n \n 전화번호\n 업체\n 비고\n \n \n \n \n 070-4578-1711\n 오케이 금융 대출\n 대출 광고\n \n \n 070-4518-2735\n 오케이 금융 대출\n 광고\n \n \n 1670-0283\n 오케이 금융 대출\n 광고\n \n \n 02-6238-0730\n 여론조사기관\n 보험 관련\n \n \n 070-8977-3754\n SK 기변센터\n 스마트폰 광고\n \n \n 02-6475-4650\n 보험점검센터\n OK캐시백\n \n \n 02-2162-7404\n 투자금액지원\n 광고\n \n \n 02-6975-9391\n 주식자금대출\n 광고\n \n \n\n\n스팸이 아닌 전화번호\n\n\n \n \n 전화번호\n 업체\n 비고\n \n \n \n \n 02-1877-8462\n 흥국화재 이유다이렉트\n 자동차 보험 가입 안내\n \n \n 1688-1688\n 흥국화재 이유다이렉트\n 자동차 보험 가입 관련\n \n \n 02-323-1127\n ROTC 중앙회\n 직장 확인 및 자택 주소 확인\n \n \n 02-1661-0544\n 유플러스 알뜰 모바일\n 알뜰요금제 개통 상담\n \n \n\n"]
Title : 깃허브 블로그 실패 사례
URL : /_pages/github-pages/2022-10-17-git-hub-pages-failure-case.html
Description : GitHub Pages로 6개월동안 삽질하고 깨닫게 된 것들
Content : GitHub Pages를 개설한지 16일만에 구글 애드센스 승인을 받았습니다.
자신감을 가지고 6개월동안 블로그를 운영했습니다.
그간의 노력들이 삽질에 불과했다는 것을 깨달았습니다.

현타 포인트

가장 현타가 오는 부분은 Jekyll입니다.


제킬! 지킬을 지켜야 했어!


Jekyll이 무엇인지 모르고 일단 찍먹해봤었기 때문에
그것이 제공하는 다양한 기능과 편리함을 이용하지 못했습니다.

가장 대표적인 부분이 사이트맵 파일을 생성하는 것에 있었습니다.
자동으로 사이트맵 파일을 생성할 수 있는 방법이 있었음에도 불구하고,
저는 제가 직접 쉘 스크립트를 작성해서 xml 파일을 생성했었습니다.

포스트 작성시에 지켜야 하는 규칙

_posts/ 디렉토리에 `YYYY-MM-DD’로 시작하는
파일명으로 md 파일을 작성해야 합니다.


‘_posts’

2022-10-17-github-현타.md
2022-10-18-내일작성할블로그.md




이 규칙을 지키지 않으면 Jekyll에서 기본적으로 제공하는
사이트 맵 자동화 기능, feed.xml 파일 자동화 기능을 사용할 수 없습니다.

왜냐하면 지킬에서 참조하는 site.posts 변수는
_posts 디렉토리 안에 있는 파일들을 이용하기 때문입니다.

카테고리 분류를 하고 싶다면?

만약, 카테고리 기능을 이용하고 싶다면,
‘_posts’ 디렉토리 안에 카테고리 키워드를 입력하면 됩니다.

예를들면, Blog라는 카테고리를 이용하고 싶다면,
아래와 같은 디렉토리 구조로 파일을 업로드하면 됩니다.


‘_posts’

Blog

2022-10-17-github-현타.md
2022-10-18-내일작성할블로그.md






포스트에 테그를 입력하고 싶다면?

포스트에 테그를 입력하고 싶다면, Front Matter에 Tags를 입력하면 됩니다.

만약, ‘Blog’ 테그와 ‘Diary’ 테그를 추가하고 싶다면,
아래처럼 Front Matter를 입력하면 됩니다.

---
title: 제목을 입력합니다.
description: 포스트를 잘 나타내는 설명을 입력합니다.
tags:
- Blog
- Diary
---


모든 포스트에 대한 링크를 표시하려면

만약 모든 포스트에 대한 링크를 표기하려면
아래와 같은 Liquid 문법을 활용하시면 됩니다.


<ul>
{% for post in site.posts %}
<li>
<a href="{{ post.url }}">[{{ post.date }}] {{ post.title }}</a>
</li>
{% endfor %}
</ul>



포스트 개수를 한정해서 링크를 표시하려면

위와 같이 모든 포스트 링크를 출력하게 되면,
엄청나게 많은 포스트의 링크가 출력되게 됩니다.

그래서 3개, 5개, 10개 정도만 출력할 필요가 생깁니다.
이 때는 ‘{\%’ 구문에 ‘limit:3’처럼 개수를 한정하면 됩니다.


<ul>
{% for post in site.posts limit:3 %}
<li>
<a href="{{ post.url }}">[{{ post.date }}] {{ post.title }}</a>
</li>
{% endfor %}
</ul>



페이지에 작성된 테그들을 표시하려면

만약, 페이지에 작성된 테그들을 표시하려면
아래와 같은 Liquid 문법을 활용하시면 됩니다.

<!-- tags -->

{% for tag in page.tags %}
#️⃣{{ tag }}
{% endfor %}



도움이 되는 링크들

아래의 링크에 접속하면 Jekyll이 빌드시에 규칙을 알아볼 수 있습니다.
Jekyll을 통해서 서비스되는 콘텐츠들은 2종류로 구분할 수 있습니다.

하나는 ‘pages’이고, 나머지 하나는 ‘posts’ 입니다.
‘pages’는 고정적인 페이지를 의미하고,
‘posts’는 그때그때 작성하는 블로그 같은 개념입니다.

예를 들면, 블로그에 대한 소개나 저자에 대한 소개는
‘pages’으로 작성하면 좋고,
매일 작성하는 일기는 ‘posts’ 형식으로 작성을 하시면 됩니다.

페이지 작성 관련
https://jekyllrb.com/docs/pages/

포스트 작성 관련
https://jekyllrb.com/docs/posts/

Liquid 문법 관련
https://shopify.github.io/liquid/

이상입니다.
["GitHub Pages를 개설한지 16일만에 구글 애드센스 승인을 받았습니다. \n자신감을 가지고 6개월동안 블로그를 운영했습니다. \n그간의 노력들이 삽질에 불과했다는 것을 깨달았습니다.\n\n현타 포인트\n\n가장 현타가 오는 부분은 Jekyll입니다.\n\n\n 제킬! 지킬을 지켜야 했어!\n\n\nJekyll이 무엇인지 모르고 일단 찍먹해봤었기 때문에 \n그것이 제공하는 다양한 기능과 편리함을 이용하지 못했습니다.\n\n가장 대표적인 부분이 사이트맵 파일을 생성하는 것에 있었습니다. \n자동으로 사이트맵 파일을 생성할 수 있는 방법이 있었음에도 불구하고, \n저는 제가 직접 쉘 스크립트를 작성해서 xml 파일을 생성했었습니다.\n\n포스트 작성시에 지켜야 하는 규칙\n\n_posts/ 디렉토리에 `YYYY-MM-DD’로 시작하는 \n파일명으로 md 파일을 작성해야 합니다.\n\n\n ‘_posts’\n \n 2022-10-17-github-현타.md\n 2022-10-18-내일작성할블로그.md\n \n \n\n\n이 규칙을 지키지 않으면 Jekyll에서 기본적으로 제공하는 \n사이트 맵 자동화 기능, feed.xml 파일 자동화 기능을 사용할 수 없습니다.\n\n왜냐하면 지킬에서 참조하는 site.posts 변수는 \n_posts 디렉토리 안에 있는 파일들을 이용하기 때문입니다.\n\n카테고리 분류를 하고 싶다면?\n\n만약, 카테고리 기능을 이용하고 싶다면, \n‘_posts’ 디렉토리 안에 카테고리 키워드를 입력하면 됩니다.\n\n예를들면, Blog라는 카테고리를 이용하고 싶다면, \n아래와 같은 디렉토리 구조로 파일을 업로드하면 됩니다.\n\n\n ‘_posts’\n \n Blog\n \n 2022-10-17-github-현타.md\n 2022-10-18-내일작성할블로그.md\n \n \n \n \n\n\n포스트에 테그를 입력하고 싶다면?\n\n포스트에 테그를 입력하고 싶다면, Front Matter에 Tags를 입력하면 됩니다.\n\n만약, ‘Blog’ 테그와 ‘Diary’ 테그를 추가하고 싶다면, \n아래처럼 Front Matter를 입력하면 됩니다.\n\n---\ntitle: 제목을 입력합니다.\ndescription: 포스트를 잘 나타내는 설명을 입력합니다.\ntags:\n- Blog\n- Diary\n---\n\n\n모든 포스트에 대한 링크를 표시하려면\n\n만약 모든 포스트에 대한 링크를 표기하려면 \n아래와 같은 Liquid 문법을 활용하시면 됩니다.\n\n\n<ul>\n {% for post in site.posts %}\n <li>\n <a href=\"{{ post.url }}\">[{{ post.date }}] {{ post.title }}</a>\n </li>\n {% endfor %}\n</ul>\n\n\n\n포스트 개수를 한정해서 링크를 표시하려면\n\n위와 같이 모든 포스트 링크를 출력하게 되면, \n엄청나게 많은 포스트의 링크가 출력되게 됩니다.\n\n그래서 3개, 5개, 10개 정도만 출력할 필요가 생깁니다. \n이 때는 ‘{\\%’ 구문에 ‘limit:3’처럼 개수를 한정하면 됩니다.\n\n\n<ul>\n {% for post in site.posts limit:3 %}\n <li>\n <a href=\"{{ post.url }}\">[{{ post.date }}] {{ post.title }}</a>\n </li>\n {% endfor %}\n</ul>\n\n\n\n페이지에 작성된 테그들을 표시하려면\n\n만약, 페이지에 작성된 테그들을 표시하려면\n아래와 같은 Liquid 문법을 활용하시면 됩니다.\n\n<!-- tags -->\n\n{% for tag in page.tags %}\n #️⃣{{ tag }}\n{% endfor %}\n\n\n\n도움이 되는 링크들\n\n아래의 링크에 접속하면 Jekyll이 빌드시에 규칙을 알아볼 수 있습니다. \nJekyll을 통해서 서비스되는 콘텐츠들은 2종류로 구분할 수 있습니다.\n\n하나는 ‘pages’이고, 나머지 하나는 ‘posts’ 입니다. \n‘pages’는 고정적인 페이지를 의미하고, \n‘posts’는 그때그때 작성하는 블로그 같은 개념입니다.\n\n예를 들면, 블로그에 대한 소개나 저자에 대한 소개는 \n‘pages’으로 작성하면 좋고, \n매일 작성하는 일기는 ‘posts’ 형식으로 작성을 하시면 됩니다.\n\n페이지 작성 관련\nhttps://jekyllrb.com/docs/pages/\n\n포스트 작성 관련\nhttps://jekyllrb.com/docs/posts/\n\nLiquid 문법 관련\nhttps://shopify.github.io/liquid/\n\n이상입니다.\n"]
Title : IMHO 뜻
URL : /english/002_IMHN뜻.html
Description : 영문 메일에서 자주 사용하는 약어인 IMHO의 뜻에 대해서 설명합니다.
Content :
IMHO stands for ‘in my humble opinion’
제 겸손한 의견으로는


이상입니다.
["\n IMHO stands for ‘in my humble opinion’\n제 겸손한 의견으로는\n\n\n이상입니다.\n"]
Title : 파이썬 빈 배열 선언 방법
URL : /004_python/009-python-how-to-declare-empty-array.html
Description : 파이썬에서 빈 배열을 선언하는 방법에 대해서 설명합니다.
Content : SW 개발자들은 평생 배워야 합니다.
C, Bash Script, Python, PHP 등의 다양한 언어를 사용하다보면
서로 다른 프로그래밍 문법을 혼동해서 사용하는 경우가 있습니다.

C언어에서 배열 선언

예를들어, C 문법에서 배열을 선언하고자 한다면,
int array[10]; 구문으로 가능합니다.

int array[10];


Bash 스크립트에서 배열 선언

반면, Bash 쉘 스크립트에서는 아래의 구문으로 배열을 선언합니다.

ARRAY=()


Bash 스크립트에서 연관 배열 선언

Bash 쉘 스크립트에서 연관 배열 선언하는 문법은 조금 다릅니다.

declare -A ASS_ARRAY


파이썬에서 배열 선언 (리스트 선언)

사실 파이썬에서 배열을 선언하는 명령은 없습니다.
엄밀히 말하면 리스트를 선언한다고 표현을 해야 합니다.
편의상 이 글에서는 ‘리스트’ 대신 ‘배열’으로 지칭하겠습니다.

myList = []


파이썬에서 배열에 항목 추가

추가적으로 파이썬에서 배열에 항목을 추가하는 방법도 설명합니다.

myList = []

myList.append("https://boyinblue.github.io")
myList.append("https://blog.naver.com/boyinblue")


파이썬에서 배열의 크기 확인

파이썬에서 배열의 킄기를 확인하려면 len()
함수를 사용하면 됩니다.

myList = []

myList.append("https://boyinblue.github.io")
myList.append("https://blog.naver.com/boyinblue")

print("배열 크기 :", len(myList))


파이썬에서 배열 순회하는 방법(#1)

파이썬에서 배열을 순회하는 방법은 여러가지가 있겠습니다.
인덱스를 통해서 순회하는 방법이 있고, 그렇지 않은 방법이 있습니다.

아래는 인덱스를 이용하지 않고 배열을 순회하는 방법입니다.

myList = []

myList.append("https://boyinblue.github.io")
myList.append("https://blog.naver.com/boyinblue")

for item in myList:
print("URL : ", item)


파이썬에서 배열 순회하는 방법(#2)

명시적으로 항목 번호를 인덱싱하면서 탐색하는 방법입니다.

#!/usr/bin/env python3

myList = []

myList.append("https://boyinblue.github.io")
myList.append("https://blog.naver.com/boyinblue")

for id in range(len(myList)):
print("URL[{}] : {}".format( id, myList[id]))


요약

✔️ 파이썬에서는 배열이 아니라 리스트라는 용어를 사용한다.

✔️ 선언은 myArray = [] 와 같이 하면 된다.

✔️ 리스트의 크기를 확인하려면 len(myList)와 같은
형식으로 작성하면 된다.

이상입니다.
["SW 개발자들은 평생 배워야 합니다. \nC, Bash Script, Python, PHP 등의 다양한 언어를 사용하다보면 \n서로 다른 프로그래밍 문법을 혼동해서 사용하는 경우가 있습니다.\n\nC언어에서 배열 선언\n\n예를들어, C 문법에서 배열을 선언하고자 한다면, \nint array[10]; 구문으로 가능합니다.\n\nint array[10];\n\n\nBash 스크립트에서 배열 선언\n\n반면, Bash 쉘 스크립트에서는 아래의 구문으로 배열을 선언합니다.\n\nARRAY=()\n\n\nBash 스크립트에서 연관 배열 선언\n\nBash 쉘 스크립트에서 연관 배열 선언하는 문법은 조금 다릅니다.\n\ndeclare -A ASS_ARRAY\n\n\n파이썬에서 배열 선언 (리스트 선언)\n\n사실 파이썬에서 배열을 선언하는 명령은 없습니다. \n엄밀히 말하면 리스트를 선언한다고 표현을 해야 합니다. \n편의상 이 글에서는 ‘리스트’ 대신 ‘배열’으로 지칭하겠습니다.\n\nmyList = []\n\n\n파이썬에서 배열에 항목 추가\n\n추가적으로 파이썬에서 배열에 항목을 추가하는 방법도 설명합니다.\n\nmyList = []\n\nmyList.append(\"https://boyinblue.github.io\")\nmyList.append(\"https://blog.naver.com/boyinblue\")\n\n\n파이썬에서 배열의 크기 확인\n\n파이썬에서 배열의 킄기를 확인하려면 len() \n함수를 사용하면 됩니다.\n\nmyList = []\n\nmyList.append(\"https://boyinblue.github.io\")\nmyList.append(\"https://blog.naver.com/boyinblue\")\n\nprint(\"배열 크기 :\", len(myList))\n\n\n파이썬에서 배열 순회하는 방법(#1)\n\n파이썬에서 배열을 순회하는 방법은 여러가지가 있겠습니다. \n인덱스를 통해서 순회하는 방법이 있고, 그렇지 않은 방법이 있습니다.\n\n아래는 인덱스를 이용하지 않고 배열을 순회하는 방법입니다.\n\nmyList = []\n\nmyList.append(\"https://boyinblue.github.io\")\nmyList.append(\"https://blog.naver.com/boyinblue\")\n\nfor item in myList:\n print(\"URL : \", item)\n\n\n파이썬에서 배열 순회하는 방법(#2)\n\n명시적으로 항목 번호를 인덱싱하면서 탐색하는 방법입니다.\n\n#!/usr/bin/env python3\n\nmyList = []\n\nmyList.append(\"https://boyinblue.github.io\")\nmyList.append(\"https://blog.naver.com/boyinblue\")\n\nfor id in range(len(myList)):\n print(\"URL[{}] : {}\".format( id, myList[id]))\n\n\n요약\n\n✔️ 파이썬에서는 배열이 아니라 리스트라는 용어를 사용한다.\n\n✔️ 선언은 myArray = [] 와 같이 하면 된다.\n\n✔️ 리스트의 크기를 확인하려면 len(myList)와 같은 \n형식으로 작성하면 된다.\n\n이상입니다.\n"]
Title : 독자를 사로잡는 매력적인 인터뷰 기사 작성법 (이은지 강사)
URL : /_posts/diary/2022-10-14-독자를-사로잡는-매력적인-인터뷰-기사-작성법-이은지-강사.html
Description : 이은지 강사님으로부터 배운 독자를 사로잡는 매력적인 인터뷰 기사 작성 법에 대해서 기록합니다.
Content :


구분
내용
비고




강의 제목
독자를 사로잡는 매력적인 인터뷰 기사 작성법
 


선생님
이은지 강사님
 


강의 날짜
2022년 10월 14일 (금요일)
 




강의 내용 메모


시인성, 시의성이 중요하다.



제목에 숫자를 넣는게 좋다. (가급적 홀수)



국뽕 한 스푼을 넣어주는 것이 좋다. (국뽕에 좋은 것도 좋고 나쁜 것도 좋다)



‘글’은 타인을 배려하는 것이다.



광고를 광고답지 않게 우회하고 돌리는 트릭



강사님께서 게재하는 글들은 ‘먹고살잡’이라는 곳이 연재하고 계심



3번의 트리거가 있으면 글을 작성함



추상적인 단어/문장 사용X (상황에 대한 묘사에 집중!)



당시의 심정을 드러낼 수 있는 명확한 묘사



주요 마인드셋 : 호기심 유발, 세상살이, 공유마인드, 호소력, 메신저



강한 발음을 좋아함 (ex : 깜짝, 대박, 꼭, 진짜 등)



성능이 떨어지는 오래된 PC를 똥컴으로 표현



가장 중요한 것 : 제목, 썸네일, 도입부



많이 언급된 키워드 : 클래스101, 브런치



영상편집 서비스 : VREW



썸네일 이미지 제작 : 미리캔버스


강사님 정보


Mobile Phone : 010-9359-9328
주소 : 서울시 용산구 효창원로 17, 3 1306호
e-mail : komubal@naver.com
유튜브


["\n \n \n 구분\n 내용\n 비고\n \n \n \n \n 강의 제목\n 독자를 사로잡는 매력적인 인터뷰 기사 작성법\n  \n \n \n 선생님\n 이은지 강사님\n  \n \n \n 강의 날짜\n 2022년 10월 14일 (금요일)\n  \n \n \n\n\n강의 내용 메모\n\n\n 시인성, 시의성이 중요하다.\n\n\n\n 제목에 숫자를 넣는게 좋다. (가급적 홀수)\n\n\n\n 국뽕 한 스푼을 넣어주는 것이 좋다. (국뽕에 좋은 것도 좋고 나쁜 것도 좋다)\n\n\n\n ‘글’은 타인을 배려하는 것이다.\n\n\n\n 광고를 광고답지 않게 우회하고 돌리는 트릭\n\n\n\n 강사님께서 게재하는 글들은 ‘먹고살잡’이라는 곳이 연재하고 계심\n\n\n\n 3번의 트리거가 있으면 글을 작성함\n\n\n\n 추상적인 단어/문장 사용X (상황에 대한 묘사에 집중!)\n\n\n\n 당시의 심정을 드러낼 수 있는 명확한 묘사\n\n\n\n 주요 마인드셋 : 호기심 유발, 세상살이, 공유마인드, 호소력, 메신저\n\n\n\n 강한 발음을 좋아함 (ex : 깜짝, 대박, 꼭, 진짜 등)\n\n\n\n 성능이 떨어지는 오래된 PC를 똥컴으로 표현\n\n\n\n 가장 중요한 것 : 제목, 썸네일, 도입부\n\n\n\n 많이 언급된 키워드 : 클래스101, 브런치\n\n\n\n 영상편집 서비스 : VREW\n\n\n\n 썸네일 이미지 제작 : 미리캔버스\n\n\n강사님 정보\n\n\n Mobile Phone : 010-9359-9328\n 주소 : 서울시 용산구 효창원로 17, 3 1306호\n e-mail : komubal@naver.com\n 유튜브\n\n\n"]
Title : 아들이 태권도 학원 그만 다니고 싶다고 했다. (2022년 10월 17일 일기)
URL : /diary/2022-10-17.html
Description : 레이 자동차 보험 가입, 사내 어린이집 신청, 대출 상환
Content : 고등동 컴포즈커피 스위트콘라떼


지난주에 매니저께서 우리 분과에 추가적인 업무를 할당하려고 했다.
분과원분들의 의견을 여쭤보니 한 분께서 분명한 반대 의견을 주셨다.
매니저께서 나를 추가적으로 설득하셨다.
나는 다시 분과원분들을 설득하려고 티타임을 요청했다.

좀 더 편안한 분위기에서 분과원분들과 소통하기 위해서 카페에서
음료와 함께 짧은 회의를 가졌다.

우리팀에서 그 업무를 가져온다고 하더라도,
바로 꿀꺽 받아먹지는 말자는 의견이 있었다.
그런 뉘앙스로 매니저께 말씀을 드렸더니 다행히 다른 대안을 제시해주셨다.

고등동 컴포즈커피는 딸기라떼가 맛있다.
3,500원인데도 양도 푸짐하고 맛도 좋다.
특히, 딸기 라떼 특유의 상큼함이 참 인상적이다.

하지만, 오늘은 특별히 새로운 메뉴는 스위트콘 라떼를 먹어봤다.
과도하게 달았지만, 달달하니까 맛있게 잘 넘어갔다.

레이 자동차 보험 가입




구분
내용
비고




보험 대상 차량
레이
 


가입금액
332,230원
 


보험사
흥국화재 이유다이렉트
 


결제
삼성카드
 




새마을금고 공제계약 대출 상황




구분
내용
비고




대출 이율
4.79%
 


기존 대출
1,140만원
 


상환 금액
3,40만원
 


잔여 대출
800만원
 


정산 이자
14,960원
 




오늘 추진한 개인적인 업무
[*] GitHub Pages에 대해서 한 단계 발전할 수 있었다. (Jekyll 이해도 증가)

오늘 추진한 회사 업무
[*] 새로운 업무에 대한 3차 세미나 수강(오후 2시 ~ 4시 20분)

[*] 매니저 면담 (새로운 업무에 대한 새로운 옵션 제안 받음)

오늘 특이점

아들이 이제 더 이상 태권도장을 다니고 싶지 않다고 했다.


["고등동 컴포즈커피 스위트콘라떼\n\n\n지난주에 매니저께서 우리 분과에 추가적인 업무를 할당하려고 했다. \n분과원분들의 의견을 여쭤보니 한 분께서 분명한 반대 의견을 주셨다. \n매니저께서 나를 추가적으로 설득하셨다. \n나는 다시 분과원분들을 설득하려고 티타임을 요청했다.\n\n좀 더 편안한 분위기에서 분과원분들과 소통하기 위해서 카페에서 \n음료와 함께 짧은 회의를 가졌다.\n\n우리팀에서 그 업무를 가져온다고 하더라도, \n바로 꿀꺽 받아먹지는 말자는 의견이 있었다. \n그런 뉘앙스로 매니저께 말씀을 드렸더니 다행히 다른 대안을 제시해주셨다.\n\n고등동 컴포즈커피는 딸기라떼가 맛있다. \n3,500원인데도 양도 푸짐하고 맛도 좋다. \n특히, 딸기 라떼 특유의 상큼함이 참 인상적이다.\n\n하지만, 오늘은 특별히 새로운 메뉴는 스위트콘 라떼를 먹어봤다.\n과도하게 달았지만, 달달하니까 맛있게 잘 넘어갔다.\n\n레이 자동차 보험 가입\n\n\n \n \n 구분\n 내용\n 비고\n \n \n \n \n 보험 대상 차량\n 레이\n  \n \n \n 가입금액\n 332,230원\n  \n \n \n 보험사\n 흥국화재 이유다이렉트\n  \n \n \n 결제\n 삼성카드\n  \n \n \n\n\n새마을금고 공제계약 대출 상황\n\n\n \n \n 구분\n 내용\n 비고\n \n \n \n \n 대출 이율\n 4.79%\n  \n \n \n 기존 대출\n 1,140만원\n  \n \n \n 상환 금액\n 3,40만원\n  \n \n \n 잔여 대출\n 800만원\n  \n \n \n 정산 이자\n 14,960원\n  \n \n \n\n\n오늘 추진한 개인적인 업무\n[*] GitHub Pages에 대해서 한 단계 발전할 수 있었다. (Jekyll 이해도 증가)\n\n오늘 추진한 회사 업무\n[*] 새로운 업무에 대한 3차 세미나 수강(오후 2시 ~ 4시 20분)\n\n[*] 매니저 면담 (새로운 업무에 대한 새로운 옵션 제안 받음)\n\n오늘 특이점\n\n 아들이 이제 더 이상 태권도장을 다니고 싶지 않다고 했다.\n\n\n"]
Title : 투다리 성남고등점에서 이웃님과 처음으로 한 잔
URL : /diary/2022/10/13/%ED%88%AC%EB%8B%A4%EB%A6%AC%EC%97%90%EC%84%9C-%EC%9D%B4%EC%9B%83%EB%8B%98%EA%B3%BC-%ED%95%9C%EC%9E%94.html
Description : 2022년 10월 13일 일기
Content : 회사에서 회식을 하고 만취한 상태에서 옆집에 사시는 이웃님께 연락을 드렸다.
처음으로 이웃님과 투다리 성남고등점에서 한 잔 했다.
이미 술에 만취한 상태에서 이웃님을 뵈었기 때문에 좋은 인상은 전혀 남기지 못한 것 같다.

오늘 투다리에서 찍은 사진은 위의 사진이 전부라서 따로 블로그는 작성하지 않았다.
한참 후에 투다리에 방문해서 찍은 사진들로 투다리 성남고등점에 대한 방문기를 작성해보았다.
투다리는 간단하게 배부르지 않게 2차로 한 잔 하기 좋은 곳임에 틀림없다.
술값은 이웃님께서 계산하셨다.

투다리 고등호반점 방문기

투다리 고등호반점 방문기
["회사에서 회식을 하고 만취한 상태에서 옆집에 사시는 이웃님께 연락을 드렸다. \n처음으로 이웃님과 투다리 성남고등점에서 한 잔 했다. \n이미 술에 만취한 상태에서 이웃님을 뵈었기 때문에 좋은 인상은 전혀 남기지 못한 것 같다.\n\n오늘 투다리에서 찍은 사진은 위의 사진이 전부라서 따로 블로그는 작성하지 않았다. \n한참 후에 투다리에 방문해서 찍은 사진들로 투다리 성남고등점에 대한 방문기를 작성해보았다. \n투다리는 간단하게 배부르지 않게 2차로 한 잔 하기 좋은 곳임에 틀림없다. \n술값은 이웃님께서 계산하셨다.\n\n투다리 고등호반점 방문기\n\n투다리 고등호반점 방문기\n"]
Title : Git 요청이 중단되었습니다. SSL TLS 보안 채널을 만들 수 없습니다. (Visual Studio Code, Git 2.37.3)
URL : /014_git/001_git_TheRequstWasAborted_CouldNotCreateSSL_TLS_SecureChannel.html
Description : Visual Studio Code에서 Git에 접근시에 요청이 중단되었습니다. SSL/TLS 보안 채널을 만들 수 없습니다. 에러가 발생할 때 조치하는 방법에 대해서 설명합니다.
Content : 문제 발생 환경

윈도우즈 환경에서 Visual Studio Code 소스 편집기를 사용하고 있습니다.
Git 버전은 2.37.3.windows.1 버전입니다.




구분
내용




운영체제
Windows 11


편집툴
Visual Studio Code


Git 버전
2.37.3.windows.1




문제의 상황

Visual Studio Code 터미널에서 git pull 명령을 수행시에
인증 정보를 입력하여도,
“요청이 중단되었습니다. SSL/TLS 보안 채널을 만들 수 없습니다.”
라는 에러 메시지가 발생함.

문제의 해결

인증 정보를 설정한다.

> git config --global --add user.name (계정명)
> git config --global --add user.email (이메일 주소)
> git config --global --add credential.helper store


위와 같이 계정명, 이메일 주소를 설정하고,
credential 정보를 로컬에 저장하도록 설정을 한다.

PowerShell에서 git pull 명령을 수행한다.

Visual Studio Code 터미널이 아닌 PowerShell에서
해당 명령을 수행하면 정상적으로 처리가 된다.

이상입니다.
["문제 발생 환경\n\n윈도우즈 환경에서 Visual Studio Code 소스 편집기를 사용하고 있습니다. \nGit 버전은 2.37.3.windows.1 버전입니다.\n\n\n \n \n 구분\n 내용\n \n \n \n \n 운영체제\n Windows 11\n \n \n 편집툴\n Visual Studio Code\n \n \n Git 버전\n 2.37.3.windows.1\n \n \n\n\n문제의 상황\n\nVisual Studio Code 터미널에서 git pull 명령을 수행시에 \n인증 정보를 입력하여도, \n“요청이 중단되었습니다. SSL/TLS 보안 채널을 만들 수 없습니다.”\n라는 에러 메시지가 발생함.\n\n문제의 해결\n\n인증 정보를 설정한다.\n\n> git config --global --add user.name (계정명)\n> git config --global --add user.email (이메일 주소)\n> git config --global --add credential.helper store\n\n\n위와 같이 계정명, 이메일 주소를 설정하고, \ncredential 정보를 로컬에 저장하도록 설정을 한다.\n\nPowerShell에서 git pull 명령을 수행한다.\n\nVisual Studio Code 터미널이 아닌 PowerShell에서 \n해당 명령을 수행하면 정상적으로 처리가 된다.\n\n이상입니다.\n"]
Title : 고등동 왕남초등학교 앞 야채트럭 드림유통 (2022년 10월 12일 일기)
URL : /901_diary/20221012_고등동_왕남초등학교_야채트럭_드림유통/
Description : 성남시 수정구 고등동 왕남초등학교 앞에는 다양한 푸드트럭이 옵니다. 매주 수요일마다 오는 야채트럭에서 갑오징어를 구입한 일상을 기록합니다.
Content :


구분
내용




날짜
2022년 10월 12일


주제
매주 수요일마다 왕남초등학교 근처에 오는 야채트럭 이야기


테그
야채트럭, 갑오징어, 드림유통


장소
성남시 수정구 고등동 왕남초등학교 근처




왕남초등학교 앞 야채트럭


우리 동네에는 푸드 트럭이 자주 온다. “떴다 곱창 전선생”이라는 곱창 트럭이 오기도 하고, 하나타코라는 타코야끼 푸드 트럭도 온다. 수요일마다는 야채 트럭이 온다.
그동안 구경만하고 한 번도 물건을 사 본적은 없다. 와이프님께서 갑오징어를 사오라는 임무를 나에게 할당하는 바람에 푸드 트럭의 정체를 알게 되었다.
그나저나, 갑오징어만 사오라고 했지, 몇 마리를 사오라고 이야기를 하지 않았다.

야채트럭 갑오징어 가격(2마리 5천원)

야채트럭에서 판매하는 갑오징어는 아주 싱싱했다. 2마리 가격은 5천원이었다. 4마리를 1만원에 구입했다.
갑오징어는 살짝 데쳐서 그냥 먹기도 했고, 짬뽕라면에 넣어서 먹기도 했다.
잡내가 거의 없이 신선한 느낌이었다.

고등행복마을에도 출몰하는 푸드트럭

그런데 이 푸드트럭의 정체가 어찌 낯설지 않다. 언젠가 산책하다가 고등행복마을 앞에서 이 트럭을 본 적이 있다.
번호판과 사장님의 인상착의가 일치한다. 근데 일요일에도 푸드트럭 장사를 하시나보다. 사진을 언제 찍었는지 봤더니 2022년 9월 25일 일요일이다.

충격 반전! 사장님은 용인시 수지구에서 오신다

카드 계산이 가능해서 이 점이 참 마음에 든다.
영수증을 살펴봤더니 “드림유통”이라고 적혀 있다.
주소지는 “경기도 용인시 수지구 수풍로 90, 102동 206호”다.
주소가 아파트인걸보면 따로 업장을 가지고 영업을 하시는게 아닌가보다.
따로 월세를 내지 않으시다보니 좀 더 저렴하게 판매하시는게 아닌가 싶기도 하다.

고등동 푸드트럭 더보기






성남시 고등동 푸드트럭 《떴다 곱창 정선생》오는날 및 전화번호
성남시 수정구 고등동에 이사 온 이후로 고등동 생활에 점차 익숙해져가고 있습니다. 고등동에서 생활하면서 알게 된 생활 정보들을 하나씩 기록해가고 있는 중입니다. 오늘은 왕남초등학교와 호반써밋판교밸리아..









["\n \n \n 구분\n 내용\n \n \n \n \n 날짜\n 2022년 10월 12일\n \n \n 주제\n 매주 수요일마다 왕남초등학교 근처에 오는 야채트럭 이야기\n \n \n 테그\n 야채트럭, 갑오징어, 드림유통\n \n \n 장소\n 성남시 수정구 고등동 왕남초등학교 근처\n \n \n\n\n왕남초등학교 앞 야채트럭\n\n\n우리 동네에는 푸드 트럭이 자주 온다. “떴다 곱창 전선생”이라는 곱창 트럭이 오기도 하고, 하나타코라는 타코야끼 푸드 트럭도 온다. 수요일마다는 야채 트럭이 온다. \n그동안 구경만하고 한 번도 물건을 사 본적은 없다. 와이프님께서 갑오징어를 사오라는 임무를 나에게 할당하는 바람에 푸드 트럭의 정체를 알게 되었다. \n그나저나, 갑오징어만 사오라고 했지, 몇 마리를 사오라고 이야기를 하지 않았다.\n\n야채트럭 갑오징어 가격(2마리 5천원)\n\n야채트럭에서 판매하는 갑오징어는 아주 싱싱했다. 2마리 가격은 5천원이었다. 4마리를 1만원에 구입했다. \n갑오징어는 살짝 데쳐서 그냥 먹기도 했고, 짬뽕라면에 넣어서 먹기도 했다. \n잡내가 거의 없이 신선한 느낌이었다.\n\n고등행복마을에도 출몰하는 푸드트럭\n\n그런데 이 푸드트럭의 정체가 어찌 낯설지 않다. 언젠가 산책하다가 고등행복마을 앞에서 이 트럭을 본 적이 있다. \n번호판과 사장님의 인상착의가 일치한다. 근데 일요일에도 푸드트럭 장사를 하시나보다. 사진을 언제 찍었는지 봤더니 2022년 9월 25일 일요일이다.\n\n충격 반전! 사장님은 용인시 수지구에서 오신다\n\n카드 계산이 가능해서 이 점이 참 마음에 든다. \n영수증을 살펴봤더니 “드림유통”이라고 적혀 있다. \n주소지는 “경기도 용인시 수지구 수풍로 90, 102동 206호”다. \n주소가 아파트인걸보면 따로 업장을 가지고 영업을 하시는게 아닌가보다. \n따로 월세를 내지 않으시다보니 좀 더 저렴하게 판매하시는게 아닌가 싶기도 하다.\n\n고등동 푸드트럭 더보기\n\n\n\n\n \n \n 성남시 고등동 푸드트럭 《떴다 곱창 정선생》오는날 및 전화번호\n 성남시 수정구 고등동에 이사 온 이후로 고등동 생활에 점차 익숙해져가고 있습니다. 고등동에서 생활하면서 알게 된 생활 정보들을 하나씩 기록해가고 있는 중입니다. 오늘은 왕남초등학교와 호반써밋판교밸리아..\n \n \n \n \n \n \n\n\n\n"]
Title : 홍천 비발디파크 앤트월드 키즈카페 이용 후기
URL : /diary/2022/10/10/%ED%99%8D%EC%B2%9C-%EC%97%AC%ED%96%89-%EB%B9%84%EB%B0%9C%EB%94%94%ED%8C%8C%ED%81%AC-%EC%95%A4%ED%8A%B8%EC%9B%94%EB%93%9C-%ED%82%A4%EC%A6%88%EC%B9%B4%ED%8E%98.html
Description : 홍천 비발디파크에서 1박 2일동안 투숙했다. 2일차에 이용했던 앤트월드 키즈파케에 대해 기록한다.
Content : 비발디 파크에는 앤트월드라는 엄청 큰 키즈카페가 있다.
두 아들을 데리고 앤트월드에서 2시간동안 놀았다.
아들들은 잘 놀았는데, 나는 조금 힘들었다.

둘째 아들이 워낙 귀엽다보니, 베이비 시터를 자처하는 누나들이 많았다.
어떤 누나가 계속 따라다니면서 예뻐해줘서 편하게 볼 수 있었다.

오픈하기 30분 전에 출발했지만, 대기번호가 31번이었다.
미리가서 번호표 뽑고 기다리고, 들어가기 위해서 또 기다렸다.

앤트월드 이용 방법


오픈 시간 : 오전 10시
예약 : 미리 도착해서 순번을 받아야 함.
입장 : 1번부터 순차적으로 입장
시간 : 2시간 (늦게 입장하면 늦게 퇴장)
양말을 꼭 착용해야 함
물을 미리 준비할 것 (가격이 사악함)


식사 이력




구분
메뉴
비고




아침
 
 


점심
퇴촌
 


저녁
 
 




지출




상품
가격
구입처
비고




굿모닝 굿밀크
1,580원
노브랜드 강남세곡점
 


페리오 키즈 포켓몬 칫솔세트
8,980원
노브랜드 강남세곡점
 


햇사레 복숭아 4kg
22,800원
노브랜드 강남세곡점
 



["비발디 파크에는 앤트월드라는 엄청 큰 키즈카페가 있다. \n두 아들을 데리고 앤트월드에서 2시간동안 놀았다. \n아들들은 잘 놀았는데, 나는 조금 힘들었다.\n\n둘째 아들이 워낙 귀엽다보니, 베이비 시터를 자처하는 누나들이 많았다. \n어떤 누나가 계속 따라다니면서 예뻐해줘서 편하게 볼 수 있었다.\n\n오픈하기 30분 전에 출발했지만, 대기번호가 31번이었다. \n미리가서 번호표 뽑고 기다리고, 들어가기 위해서 또 기다렸다.\n\n앤트월드 이용 방법\n\n\n 오픈 시간 : 오전 10시\n 예약 : 미리 도착해서 순번을 받아야 함.\n 입장 : 1번부터 순차적으로 입장\n 시간 : 2시간 (늦게 입장하면 늦게 퇴장)\n 양말을 꼭 착용해야 함\n 물을 미리 준비할 것 (가격이 사악함)\n\n\n식사 이력\n\n\n \n \n 구분\n 메뉴\n 비고\n \n \n \n \n 아침\n  \n  \n \n \n 점심\n 퇴촌\n  \n \n \n 저녁\n  \n  \n \n \n\n\n지출\n\n\n \n \n 상품\n 가격\n 구입처\n 비고\n \n \n \n \n 굿모닝 굿밀크\n 1,580원\n 노브랜드 강남세곡점\n  \n \n \n 페리오 키즈 포켓몬 칫솔세트\n 8,980원\n 노브랜드 강남세곡점\n  \n \n \n 햇사레 복숭아 4kg\n 22,800원\n 노브랜드 강남세곡점\n  \n \n \n\n"]
Title : 홍천 여행 비발디파크 1박 2일 투숙 후기
URL : /diary/2022/10/09/%ED%99%8D%EC%B2%9C-%EC%97%AC%ED%96%89-%EB%B9%84%EB%B0%9C%EB%94%94%ED%8C%8C%ED%81%AC-1%EB%B0%95-2%EC%9D%BC.html
Description : 2022년 10월 9일 1박 2일동안 홍천 비발디파크에서 투숙한 기록을 남깁니다.
Content : 요약

인상적인 점

홍천 농협 하나로마트에서 구입한 판두부가 너무 맛있었다.
다음에 방문하면 꼭 다시 구입해서 먹고 싶다.

구입한 물건들




상품
구입가격
구입처
비고




우리술 싸이월드 도토리막걸리
2,900원
이마트24 용문휴게소점
 


뽀로로 바나나우유 140ml
1,200원
이마트24 용문휴게소점
 



["요약\n\n인상적인 점\n\n홍천 농협 하나로마트에서 구입한 판두부가 너무 맛있었다. \n다음에 방문하면 꼭 다시 구입해서 먹고 싶다.\n\n구입한 물건들\n\n\n \n \n 상품\n 구입가격\n 구입처\n 비고\n \n \n \n \n 우리술 싸이월드 도토리막걸리\n 2,900원\n 이마트24 용문휴게소점\n  \n \n \n 뽀로로 바나나우유 140ml\n 1,200원\n 이마트24 용문휴게소점\n  \n \n \n\n"]
Title : 네이버에서 티스토리 블로그의 플러스맵 뷰어 페이지가 잔뜩 검색되는 현상
URL : /tistory/2022/09/29/tistory-plus-map-viewer.html
Description : 제 티스토리 블로그가 네이버에서 잘 검색되는지 살펴봤습니다. 플러스맵 뷰어라는 의미없는 빈 페이지들이 잔뜩 수집되어 있었습니다.
Content : 언젠가 티스토리 블로그의 제목을 변경한 이후로,
네이버 검색 유입이 뚝 끊인 것을 확인했습니다.
확인해보니 제 티스토리 블로그가 네이버에서 전혀 검색이 되지 않았습니다.
소위 말하는 블로그 저품이 온 상황이었습니다.

그 이후부터는 몹시 힘든 시간을 보내야 했습니다.
양질의 컨텐츠를 생산하기 위해서 많은 노력을 기울였습니다.
구글 검색 엔진과 다음 검색 엔진을 통해서 제법 많은 트래픽이 들어왔습니다.
반면, 네이버 검색 엔진의 유입은 극히 미미했습니다.

더 많은 트래픽은 더 많은 수익을 의미합니다.
국문으로 된 콘텐츠들은 네이버에서 검색되지 않으면 많은 트래픽을 유발하기 어렵습니다.
다행히 한 달이 조금 지난 지금은 네이버 검색 엔진 유입 비율이 가장 높아졌습니다.

네이버 검색 반영 확인


포털에서 블로그 주소로 검색해보면 됨


다들 알고 계시겠지만, 네이버 검색 반영을 확인해보려면
네이버 포털에서 사이트 주소를 입력하면 됩니다.
만약 해당 사이트 콘텐츠가 검색 결과에 나오면 검색 반영이 된 것입니다.
그렇지 않으면 블로그가 검색에 누락된 상태입니다.
이전에는 잘 검색이 되었는데, 갑자기 블로그가 전혀 검색이 안된다면 저품 낙인이 찍힌 것입니다.
그 다음부터는 가시밭길을 가야 합니다.


PC와 모바일 둘 다 해볼 것
PC와 모바일 모두에서 검색을 해봐야 합니다.
왜냐하면, PC에서는 검색이 되는데 모바일에서는 검색이 안 되는 경우가 있기 때문입니다.
제 경우는 PC에서의 검색은 이뤄졌으나,
모바일에서는 전혀 검색이 안 되는 상황이었습니다.
이것을 회복하는데는 상당히 많은 시간과 노력이 필요했습니다.


카카오 플러스맵 뷰어?


어느날 스마트폰으로 네이버에서 제 티스토리 블로그를 검색해 봤습니다.
위의 화면처럼 플러스맵 뷰어라는 글들만 잔뜩 검색이 되었습니다.
해당 링크를 클릭해보면 내용이 전혀 없습니다.

내용이 전혀 없는 페이지가 잔뜩 검색 엔진에 반영이 되었다는 것은 좋지 않은 상황입니다.
양질의 콘텐츠들이 검색되는게 아니라 빈 페이지가 잔뜩 검색이 되는 것은 누가 봐도 좋지 않은 상황입니다.
아래 페이지들은 검색 엔진이 싫어하는 페이지들입니다.

의미가 없는 페이지
링크가 과도하게 많은 페이지
페이지별로 유사한 점이 많은 페이지 (유사 페이지)


문제의 해결 방법 (고객센터)

이 문제는 고객센터에 문의해서 해결했습니다.
티스토리쪽은 의미없는 빈 페이지들을 자동으로 생성했으며,
네이버 검색엔진은 의미없는 빈 페이지들을 잔뜩 수집한 상황이었습니다.

고객센터에 문의를 했더니, 이 문제가 해결되었습니다.
이것이 직접적으로 네이버 검색 유입을 늘리는데 영향을 줬는지는 알 수 없습니다.
하지만 약 한 달이 지난 지금 제 티스토리 블로그는 네이버에서 가장 많이 들어옵니다.

이상입니다.
["언젠가 티스토리 블로그의 제목을 변경한 이후로, \n네이버 검색 유입이 뚝 끊인 것을 확인했습니다. \n확인해보니 제 티스토리 블로그가 네이버에서 전혀 검색이 되지 않았습니다. \n소위 말하는 블로그 저품이 온 상황이었습니다.\n\n그 이후부터는 몹시 힘든 시간을 보내야 했습니다. \n양질의 컨텐츠를 생산하기 위해서 많은 노력을 기울였습니다. \n구글 검색 엔진과 다음 검색 엔진을 통해서 제법 많은 트래픽이 들어왔습니다. \n반면, 네이버 검색 엔진의 유입은 극히 미미했습니다.\n\n더 많은 트래픽은 더 많은 수익을 의미합니다. \n국문으로 된 콘텐츠들은 네이버에서 검색되지 않으면 많은 트래픽을 유발하기 어렵습니다. \n다행히 한 달이 조금 지난 지금은 네이버 검색 엔진 유입 비율이 가장 높아졌습니다.\n\n네이버 검색 반영 확인\n\n\n 포털에서 블로그 주소로 검색해보면 됨\n\n\n다들 알고 계시겠지만, 네이버 검색 반영을 확인해보려면 \n네이버 포털에서 사이트 주소를 입력하면 됩니다. \n만약 해당 사이트 콘텐츠가 검색 결과에 나오면 검색 반영이 된 것입니다. \n그렇지 않으면 블로그가 검색에 누락된 상태입니다. \n이전에는 잘 검색이 되었는데, 갑자기 블로그가 전혀 검색이 안된다면 저품 낙인이 찍힌 것입니다. \n그 다음부터는 가시밭길을 가야 합니다.\n\n\n PC와 모바일 둘 다 해볼 것\nPC와 모바일 모두에서 검색을 해봐야 합니다. \n왜냐하면, PC에서는 검색이 되는데 모바일에서는 검색이 안 되는 경우가 있기 때문입니다. \n제 경우는 PC에서의 검색은 이뤄졌으나, \n모바일에서는 전혀 검색이 안 되는 상황이었습니다. \n이것을 회복하는데는 상당히 많은 시간과 노력이 필요했습니다.\n\n\n카카오 플러스맵 뷰어?\n\n\n어느날 스마트폰으로 네이버에서 제 티스토리 블로그를 검색해 봤습니다. \n위의 화면처럼 플러스맵 뷰어라는 글들만 잔뜩 검색이 되었습니다. \n해당 링크를 클릭해보면 내용이 전혀 없습니다.\n\n내용이 전혀 없는 페이지가 잔뜩 검색 엔진에 반영이 되었다는 것은 좋지 않은 상황입니다. \n양질의 콘텐츠들이 검색되는게 아니라 빈 페이지가 잔뜩 검색이 되는 것은 누가 봐도 좋지 않은 상황입니다. \n아래 페이지들은 검색 엔진이 싫어하는 페이지들입니다.\n\n 의미가 없는 페이지\n 링크가 과도하게 많은 페이지\n 페이지별로 유사한 점이 많은 페이지 (유사 페이지)\n\n\n문제의 해결 방법 (고객센터)\n\n이 문제는 고객센터에 문의해서 해결했습니다. \n티스토리쪽은 의미없는 빈 페이지들을 자동으로 생성했으며, \n네이버 검색엔진은 의미없는 빈 페이지들을 잔뜩 수집한 상황이었습니다.\n\n고객센터에 문의를 했더니, 이 문제가 해결되었습니다. \n이것이 직접적으로 네이버 검색 유입을 늘리는데 영향을 줬는지는 알 수 없습니다. \n하지만 약 한 달이 지난 지금 제 티스토리 블로그는 네이버에서 가장 많이 들어옵니다.\n\n이상입니다.\n"]
Title : SEC_ERROR_PKCS11_GENERAL_ERROR 에러 발생시 조치 방법
URL : /022_firefox/001-firefox-SEC_ERROR_PKCS11_GENERAL_ERROR.html
Description : Firefox 웹브라우저에서 SEC_ERROR_PKCS11_GENERAL_ERROR 에러가 발생할 경우 조치하는 방법에 대해서 설명합니다.
Content : 사무실에서 사용하는 Note PC의 웹브라우저로 사내 인트라넷을 접속해보면 SEC_ERROR_PKCS11_GENERAL_ERROR라는 에러가 지속적으로 발생하기 시작했습니다. Microsoft Edge, Chrome, Firefox 등을 사용하고 있는데 Chrome은 괜찮은데 유독 Microsoft Edge와 Firefox에서만 접속 장애가 발생하더군요.

본 페이지에서는 Firefox 웹브라우저를 이용하여 웹사이트에 접속시에 SEC_ERROR_PKCS11_GENERAL_ERROR라는 에러 메시지가 발생하면서 접속되지 않을 때 조치하는 방법에 대해서 설명하고자 합니다.

임시 조치 방법

해당 문제를 해결하기 위해서는 레지스트리 편집기를 실행시켜서 아래 레지스트리 값으로 수정하거나 추가하면 손쉽게 해결할 수 있습니다.

1. 레지스트리 편집기 실행

가장 먼저 윈도우 키 + R 키를 동시에 눌러서 regedit를 입력하여 레지스트리 편집기를 실행시킵니다.

2. HKEY_LOCAL_MACHINE 디렉토리를 선택합니다.

최상위 경로에서 HKEY_LOCAL_MACHINE 항목을 선택합니다.

3. SOFTWARE 디렉토리를 선택합니다.

HKEY_LOCAL_MACHINE 디렉토리 하위에 있는 SOFTWARE 디렉토리를 선택합니다.


HKEY_LOCAL_MACHINE\SOFTWARE


4. Policies 디렉토리를 선택합니다.

HKEY_LOCAL_MACHINE\SOFTWARE 디렉토리 하위에 있는 Policies 디렉토리를 선택합니다.


HKEY_LOCAL_MACHINE\SOFTWARE\Policies


5. Mozilla 디렉토리를 선택합니다.

HKEY_LOCAL_MACHINE\SOFTWARE\Policies 디렉토리 하위에 있는 Mozilla 디렉토리를 선택합니다.


HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Mozilla


6. Firefox 디렉토리를 선택합니다.

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Mozilla 디렉토리 하위에 있는 Firefox 디렉토리를 선택합니다.

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Mozilla\Firefox


7. Preferences 디렉토리를 선택합니다. 없으면 생성합니다.

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Mozilla\Firefox 디렉토리 하위에 있는 Preferences 디렉토리를 선택합니다.
만약 해당 키값이 없다면 마우스 오른쪽 버튼을 이용해서 새로 만들기를 선택하시고, K를 눌러 Preferences 키를 생성합니다.

8. security.osclientcerts.autoload 값을 0으로 변경합니다.

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Mozilla\Firefox\Preferences 디렉토리에서 security.osclientcerts.autoload 키를 선택해서 값을 0으로 변경합니다. 만약 해당 값이 없다면 새로 만들기 메뉴를 이용해서 DWORD(32비트) 값을 추가하고 값은 0으로 지정해줍니다.

9. Firefox를 재시작합니다.

그 후에 Firefox를 시작하면 해당 문제가 해결됩니다.

관련 링크

해당 내용은 아래의 페이지에서 정보를 얻었습니다.






Expected behavior As a paas-templates operator and user In order to use portals and web ui components with Firefox browser I need to adapt web access to entreprise strategy Observed behavior Since ...
None








["사무실에서 사용하는 Note PC의 웹브라우저로 사내 인트라넷을 접속해보면 SEC_ERROR_PKCS11_GENERAL_ERROR라는 에러가 지속적으로 발생하기 시작했습니다. Microsoft Edge, Chrome, Firefox 등을 사용하고 있는데 Chrome은 괜찮은데 유독 Microsoft Edge와 Firefox에서만 접속 장애가 발생하더군요.\n\n본 페이지에서는 Firefox 웹브라우저를 이용하여 웹사이트에 접속시에 SEC_ERROR_PKCS11_GENERAL_ERROR라는 에러 메시지가 발생하면서 접속되지 않을 때 조치하는 방법에 대해서 설명하고자 합니다.\n\n임시 조치 방법\n\n해당 문제를 해결하기 위해서는 레지스트리 편집기를 실행시켜서 아래 레지스트리 값으로 수정하거나 추가하면 손쉽게 해결할 수 있습니다.\n\n1. 레지스트리 편집기 실행\n\n가장 먼저 윈도우 키 + R 키를 동시에 눌러서 regedit를 입력하여 레지스트리 편집기를 실행시킵니다.\n\n2. HKEY_LOCAL_MACHINE 디렉토리를 선택합니다.\n\n최상위 경로에서 HKEY_LOCAL_MACHINE 항목을 선택합니다.\n\n3. SOFTWARE 디렉토리를 선택합니다.\n\nHKEY_LOCAL_MACHINE 디렉토리 하위에 있는 SOFTWARE 디렉토리를 선택합니다.\n\n\n HKEY_LOCAL_MACHINE\\SOFTWARE\n\n\n4. Policies 디렉토리를 선택합니다.\n\nHKEY_LOCAL_MACHINE\\SOFTWARE 디렉토리 하위에 있는 Policies 디렉토리를 선택합니다.\n\n\n HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\n\n\n5. Mozilla 디렉토리를 선택합니다.\n\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Policies 디렉토리 하위에 있는 Mozilla 디렉토리를 선택합니다.\n\n\n HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Mozilla\n\n\n6. Firefox 디렉토리를 선택합니다.\n\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Mozilla 디렉토리 하위에 있는 Firefox 디렉토리를 선택합니다.\n\n HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Mozilla\\Firefox\n\n\n7. Preferences 디렉토리를 선택합니다. 없으면 생성합니다.\n\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Mozilla\\Firefox 디렉토리 하위에 있는 Preferences 디렉토리를 선택합니다. \n만약 해당 키값이 없다면 마우스 오른쪽 버튼을 이용해서 새로 만들기를 선택하시고, K를 눌러 Preferences 키를 생성합니다.\n\n8. security.osclientcerts.autoload 값을 0으로 변경합니다.\n\nHKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Mozilla\\Firefox\\Preferences 디렉토리에서 security.osclientcerts.autoload 키를 선택해서 값을 0으로 변경합니다. 만약 해당 값이 없다면 새로 만들기 메뉴를 이용해서 DWORD(32비트) 값을 추가하고 값은 0으로 지정해줍니다.\n\n9. Firefox를 재시작합니다.\n\n그 후에 Firefox를 시작하면 해당 문제가 해결됩니다.\n\n관련 링크\n\n해당 내용은 아래의 페이지에서 정보를 얻었습니다.\n\n\n\n\n \n \n Expected behavior As a paas-templates operator and user In order to use portals and web ui components with Firefox browser I need to adapt web access to entreprise strategy Observed behavior Since ...\n None\n \n \n \n \n \n \n\n\n"]
Title : 스캠 주의 Your subscription suspended netflix 넷플릭스 구독 관련 스캠 메일 사례
URL : /020_security/001_netflix_subscription_scam.html
Description : 본 페이지에서는 넷플릭스 계정 관련 스캠 사례를 공유합니다.
Content : 다양한 방법들로 우리의 계정과 자산을 노리는 스캠 사례가 많이 있습니다.
필자의 경우도 최근에 스미싱을 비롯한 여러 종류의 스캠 시도들을 경험했습니다.
가장 마음 아픈 부분은, 오랫동안 사용했던 트위터 계정이 해킹당해서 사용 불가능한 상황이 된 것입니다.
본 페이지에서는 넷플릭스를 사칭한 메일을 통한 스캠 시도 사례를 공유합니다.

Your subscription suspended: Netflix

필자의 메일에 아래와 같은 메일이 수신되었습니다.
다행히도 해당 메일은 스팸 메일로 분류되어 있었습니다.

간혹 다음 메일 서비스가 일반적인 메일을 스팸으로 오인식하는 경우가 있어서,
간혹 스팸 메일을 살펴보는 편입니다.



메일을 보낸 사람을 먼저 살펴보았습니다. 보낸 사람의 이름은 “Invoice Netflix”로 되어 있고,
보낸 사람의 이메일 주소는 “service817470@servicess.com”으로 되어 있었습니다.

“RESTART MEMBERSHIP”이라는 버튼은 “https://cartoonresearch.com/current/NETFLIX/login” 라는 주소로 연결이 되어 있었습니다.
메일 주소도, 링크 주소의 도메인 네임도 넷플릭스와는 전혀 상관이 없다는 것을 확인할 수 있었습니다.

스캠의 의도?

이번 메일을 통한 스캠의 의도는 트래픽을 유발하기 위함인 것 같습니다.
아시겠지만, 더 많은 트래픽은 더 많은 광고 수익을 의미하기 때문입니다.



해당 페이지에 접속을 해봤더니, 광고 배너가 붙어있는 웹페이지였습니다.
더 많은 사람들이 접속을 할수록 더 많은 광고 수익을 얻을 수 있기 때문입니다.

스캠 관련 다른 사례들

아래는 제가 경험한 다양한 사례의 스캠 및 해킹 피해 사례입니다.

국외배송 결과 관련 스미싱

국외배송 관련 스미싱

미프진 코리아 본사를 사칭한 트위터 계정 해킹

트위터 계정 해킹 피해 사례

바이넨스 사칭 메일 스캠

바이넨스 사칭 메일 스캠

결론

다양한 방법을 통한 스캠 시도들이 우리의 계정 및 자산을 위협하고 있습니다.
의심되는 이메일 또는 문자를 수신하였다면 아래 사항들을 체크해보시기 바랍니다.

의심되는 이메일 수신시


보낸 사람의 메일 주소를 살펴봅니다.
링크가 있을 경우 링크 주소를 살펴봅니다.
첨부파일이 있을 경우 다운로드하거나 실행시키지 않습니다.


의심되는 문자 수신시


링크가 있을 경우 접속하지 마시기 바랍니다.
첨부파일이 있을 경우, 다운로드 하거나 실행시키지 않도록 합니다.


이상입니다.
["다양한 방법들로 우리의 계정과 자산을 노리는 스캠 사례가 많이 있습니다. \n필자의 경우도 최근에 스미싱을 비롯한 여러 종류의 스캠 시도들을 경험했습니다. \n가장 마음 아픈 부분은, 오랫동안 사용했던 트위터 계정이 해킹당해서 사용 불가능한 상황이 된 것입니다. \n본 페이지에서는 넷플릭스를 사칭한 메일을 통한 스캠 시도 사례를 공유합니다.\n\nYour subscription suspended: Netflix\n\n필자의 메일에 아래와 같은 메일이 수신되었습니다. \n다행히도 해당 메일은 스팸 메일로 분류되어 있었습니다.\n\n간혹 다음 메일 서비스가 일반적인 메일을 스팸으로 오인식하는 경우가 있어서, \n간혹 스팸 메일을 살펴보는 편입니다.\n\n\n\n메일을 보낸 사람을 먼저 살펴보았습니다. 보낸 사람의 이름은 “Invoice Netflix”로 되어 있고, \n보낸 사람의 이메일 주소는 “service817470@servicess.com”으로 되어 있었습니다.\n\n“RESTART MEMBERSHIP”이라는 버튼은 “https://cartoonresearch.com/current/NETFLIX/login” 라는 주소로 연결이 되어 있었습니다. \n메일 주소도, 링크 주소의 도메인 네임도 넷플릭스와는 전혀 상관이 없다는 것을 확인할 수 있었습니다.\n\n스캠의 의도?\n\n이번 메일을 통한 스캠의 의도는 트래픽을 유발하기 위함인 것 같습니다. \n아시겠지만, 더 많은 트래픽은 더 많은 광고 수익을 의미하기 때문입니다.\n\n\n\n해당 페이지에 접속을 해봤더니, 광고 배너가 붙어있는 웹페이지였습니다. \n더 많은 사람들이 접속을 할수록 더 많은 광고 수익을 얻을 수 있기 때문입니다.\n\n스캠 관련 다른 사례들\n\n아래는 제가 경험한 다양한 사례의 스캠 및 해킹 피해 사례입니다.\n\n국외배송 결과 관련 스미싱\n\n국외배송 관련 스미싱\n\n미프진 코리아 본사를 사칭한 트위터 계정 해킹\n\n트위터 계정 해킹 피해 사례\n\n바이넨스 사칭 메일 스캠\n\n바이넨스 사칭 메일 스캠\n\n결론\n\n다양한 방법을 통한 스캠 시도들이 우리의 계정 및 자산을 위협하고 있습니다. \n의심되는 이메일 또는 문자를 수신하였다면 아래 사항들을 체크해보시기 바랍니다.\n\n의심되는 이메일 수신시\n\n\n 보낸 사람의 메일 주소를 살펴봅니다.\n 링크가 있을 경우 링크 주소를 살펴봅니다.\n 첨부파일이 있을 경우 다운로드하거나 실행시키지 않습니다.\n\n\n의심되는 문자 수신시\n\n\n 링크가 있을 경우 접속하지 마시기 바랍니다.\n 첨부파일이 있을 경우, 다운로드 하거나 실행시키지 않도록 합니다.\n\n\n이상입니다.\n"]
Title : 이사 비용 정리 (2022년 7월 10일)
URL : /_posts/diary/2022-07-10-이사비용정리.html
Description : 2022년 7월 10일 의왕시 오전동에서 성남시 고등동으로 이사했다. 이사하면서 발생한 비용을 정리한다.
Content : 임대보증

집주인이 장기 임대사업자인 관계로, 임대보증 가입 의무가 있다.
보증에 발생한 금액은 443,640원이고, 임대인이 75%를 부담하고,
임차인이 25%를 부담하게 되어 있다.




구분
금액
비고




임대인
332,730원
75% 부담


임차인
110,910원
25% 부담


총 금액
443,640원
 




중개수수료

오전동 임대 복비
의왕시 오전동 XXXX공인중개사를 이용했다.
지류형 의왕사랑상품권을 이용할 수 있어서 실제로는 10% 할인 혜택이 있었다.

고등동 임차 복비
성남시 수정구 고등동에 있는 진짜공인중개사무소를 이용했다.
수수료 할인은 따로 없었지만, 이사 당일에 휴지 1박스를 선물로 주셨다.

이삿집 센터

19층에서 4층으로 이사를 했고,
이삿집 센터 비용은 약 130만원이 들었다.
외국인 노동자 3명과 한국인 주방 아줌마 1명으로 구성되어 있었다.

총 비용




항목
비용
비고




기존 주택 복비
122만원
할인, 지역화폐 사용, 오전동 XXXX공인중개사


신규 주택 복비
150만원
고등동 진짜공인중개사


이삿집 센터
130만원
19층 -> 저층


임대보증
11만원
보험료의 25% 부담




관련글

[금번 이사 비용 정리 (중개수수료 + 이사짐센터 = 약 400만원]https://blog.naver.com/boyinblue/222865431858](https://blog.naver.com/boyinblue/222865431858)
["임대보증\n\n집주인이 장기 임대사업자인 관계로, 임대보증 가입 의무가 있다. \n보증에 발생한 금액은 443,640원이고, 임대인이 75%를 부담하고, \n임차인이 25%를 부담하게 되어 있다.\n\n\n \n \n 구분\n 금액\n 비고\n \n \n \n \n 임대인\n 332,730원\n 75% 부담\n \n \n 임차인\n 110,910원\n 25% 부담\n \n \n 총 금액\n 443,640원\n  \n \n \n\n\n중개수수료\n\n오전동 임대 복비\n의왕시 오전동 XXXX공인중개사를 이용했다. \n지류형 의왕사랑상품권을 이용할 수 있어서 실제로는 10% 할인 혜택이 있었다.\n\n고등동 임차 복비\n성남시 수정구 고등동에 있는 진짜공인중개사무소를 이용했다. \n수수료 할인은 따로 없었지만, 이사 당일에 휴지 1박스를 선물로 주셨다.\n\n이삿집 센터\n\n19층에서 4층으로 이사를 했고, \n이삿집 센터 비용은 약 130만원이 들었다. \n외국인 노동자 3명과 한국인 주방 아줌마 1명으로 구성되어 있었다.\n\n총 비용\n\n\n \n \n 항목\n 비용\n 비고\n \n \n \n \n 기존 주택 복비\n 122만원\n 할인, 지역화폐 사용, 오전동 XXXX공인중개사\n \n \n 신규 주택 복비\n 150만원\n 고등동 진짜공인중개사\n \n \n 이삿집 센터\n 130만원\n 19층 -> 저층\n \n \n 임대보증\n 11만원\n 보험료의 25% 부담\n \n \n\n\n관련글\n\n[금번 이사 비용 정리 (중개수수료 + 이사짐센터 = 약 400만원]https://blog.naver.com/boyinblue/222865431858](https://blog.naver.com/boyinblue/222865431858)\n"]
Title : markdown table 문법
URL : /_pages/markdown/2022-06-28-markdown_table.html
Description : markdown table 문법에 대해서 기록해두는 페이지입니다.
Content : Code
|제목 1|제목 2|제목 3|제목 4|
|---|---|---|---|
|내용 1|내용 2|내용 3|내용 4|
|내용 5|내용 6|내용 7|내용 8|
|내용 9|내용 10|내용 11|내용 12|


Display




제목 1
제목 2
제목 3
제목 4




내용 1
내용 2
내용 3
내용 4


내용 5
내용 6
내용 7
내용 8


내용 9
내용 10
내용 11
내용 12




✔️ markdown 문법

markdown 문법에 대해서 기록하는 페이지입니다.
["Code\n|제목 1|제목 2|제목 3|제목 4|\n|---|---|---|---|\n|내용 1|내용 2|내용 3|내용 4|\n|내용 5|내용 6|내용 7|내용 8|\n|내용 9|내용 10|내용 11|내용 12|\n\n\nDisplay\n\n\n \n \n 제목 1\n 제목 2\n 제목 3\n 제목 4\n \n \n \n \n 내용 1\n 내용 2\n 내용 3\n 내용 4\n \n \n 내용 5\n 내용 6\n 내용 7\n 내용 8\n \n \n 내용 9\n 내용 10\n 내용 11\n 내용 12\n \n \n\n\n✔️ markdown 문법\n\nmarkdown 문법에 대해서 기록하는 페이지입니다.\n"]
Title : 굿모닝쌤 영어수업 (2022년 7월 22일)
URL : /900_english/001_goodmorningsam_belle_how_to_politely_confront_your_roommate_kims_convenience.html
Description : 2022년 7월 22일에 Belle 선생님과 진행한 수업 내용을 메모합니다.
Content :


구분
내용
비고




날짜
2022년 7월 22일
 


선생님
Belle
 


컨텐츠
How to politely confront your rommate
Kim’s Convenience




Belle 선생님에 대해서

외국계 회사를 다니고 있어서 영어의 필요성이 상당히 높습니다.
6개월 이상 굿모닝쌤이라는 곳에서 영어 수업을 받고 있는데요.




선생님
장점
단점
비고




(기억 안남)
열정적인 강의, 즉각적인 피드백
 
 


Geny
발음이 좋고, 원숙한강의
결강이 잦음
 


Belle
즉각적인 첨삭으로 완벽한 문장을 만들어주심
 
체험 수업




오늘 수업을 해주신 Belle 선생님은, 필리핀에 거주하고 계시고,
이제 4개월 된 딸이 있다고 하셨습니다.
미숙아로 1kg으로 태어났지만, 지금은 다행히 많이 컸다고 하더군요.

Vocaburary




Word
Meaning
Note




apprent
명백한
 


confront
argue
 


recently
 
강세 주의


considerate
 
발음 주의


soak
담그다
I’m looking forward to a long soak in the tub


water bill
수도 요금
동의어 hydro bill


electro bill
전기 요금
 




첨삭

Q : How do you handle conflicts?

It isn’t easy for me to confront someone.
I try to stretch my patience as much as possible.
To have a confrontation with someone is not comfortable for me.

Q : How do you handle conflicts at work?

Usually, I aovid conflicts at work.
One time, I had faced someone about our ideas.
But, we were really not on the same page.
To avoid the conflict, I gave up on my idea and I accepted his idea instead.

Q : Have you ever disagree with your boss?

I and my direct manager have a good working relationship.
So, we never have any arguments and conflicts.
However, I and my manager’s direct superior have no good relationship.

Link

How to politely confront your roommate(YouTube)
["\n \n \n 구분\n 내용\n 비고\n \n \n \n \n 날짜\n 2022년 7월 22일\n  \n \n \n 선생님\n Belle\n  \n \n \n 컨텐츠\n How to politely confront your rommate\n Kim’s Convenience\n \n \n\n\nBelle 선생님에 대해서\n\n외국계 회사를 다니고 있어서 영어의 필요성이 상당히 높습니다. \n6개월 이상 굿모닝쌤이라는 곳에서 영어 수업을 받고 있는데요.\n\n\n \n \n 선생님\n 장점\n 단점\n 비고\n \n \n \n \n (기억 안남)\n 열정적인 강의, 즉각적인 피드백\n  \n  \n \n \n Geny\n 발음이 좋고, 원숙한강의\n 결강이 잦음\n  \n \n \n Belle\n 즉각적인 첨삭으로 완벽한 문장을 만들어주심\n  \n 체험 수업\n \n \n\n\n오늘 수업을 해주신 Belle 선생님은, 필리핀에 거주하고 계시고, \n이제 4개월 된 딸이 있다고 하셨습니다. \n미숙아로 1kg으로 태어났지만, 지금은 다행히 많이 컸다고 하더군요.\n\nVocaburary\n\n\n \n \n Word\n Meaning\n Note\n \n \n \n \n apprent\n 명백한\n  \n \n \n confront\n argue\n  \n \n \n recently\n  \n 강세 주의\n \n \n considerate\n  \n 발음 주의\n \n \n soak\n 담그다\n I’m looking forward to a long soak in the tub\n \n \n water bill\n 수도 요금\n 동의어 hydro bill\n \n \n electro bill\n 전기 요금\n  \n \n \n\n\n첨삭\n\nQ : How do you handle conflicts?\n\nIt isn’t easy for me to confront someone. \nI try to stretch my patience as much as possible. \nTo have a confrontation with someone is not comfortable for me.\n\nQ : How do you handle conflicts at work?\n\nUsually, I aovid conflicts at work. \nOne time, I had faced someone about our ideas. \nBut, we were really not on the same page. \nTo avoid the conflict, I gave up on my idea and I accepted his idea instead.\n\nQ : Have you ever disagree with your boss?\n\nI and my direct manager have a good working relationship. \nSo, we never have any arguments and conflicts. \nHowever, I and my manager’s direct superior have no good relationship.\n\nLink\n\nHow to politely confront your roommate(YouTube)\n"]
Title : 색상 프로필을 만들려면 인증이 필요합니다.
URL : /008_ubuntu/010-ubuntu-xrdp-color-pkla.html
Description : XRDP 연결시 (색상 프로필을 만들려면 인증이 필요합니다.)라는 메시지가 반복적으로 표시될 경우 해결 방법
Content : 요약

/etc/polkit-1/localauthority/50-local.d 디렉토리 생성

$ sudo mkdir -p /etc/polkit-1/localauthority/50-local.d


/etc/polkit-1/localauthority/50-local.d/color.pkla 파일 편집

$ sudo vi /etc/polkit-1/localauthority/50-local.d/color.pkla


해당 파일에 아래 내용을 작성함.

[Allow colord for all users]
Identity=unix-user:*
Action=org.freedesktop.color-manager.create-device;org.freedesktop.color-manager.create-profile;org.freedesktop.color-manager.delete-device;org.freedesktop.color-manager.delete-profile;org.freedesktop.color-manager.modify-device;org.freedesktop.color-manager.modify-profile
ResultAny=yes
ResultInactive=yes
ResultActive=yes


혹은 wget으로 해당 파일을 다운로드 받아서 복사해도 됩니다.

$ wget https://raw.githubusercontent.com/boyinblue/test/main/ubuntu/color.pkla/color.pkla
$ sudo mv color.pkla /etc/polkit-1/localauthority/50-local.d/


관련 링크

우분투 22.04에서 xrdp 연결시 색상 프로필을 만들려면 인증이 필요합니다. 라는 메시지가 뜨지 않도록 조치하는 방법

이상입니다.
["요약\n\n/etc/polkit-1/localauthority/50-local.d 디렉토리 생성\n\n$ sudo mkdir -p /etc/polkit-1/localauthority/50-local.d\n\n\n/etc/polkit-1/localauthority/50-local.d/color.pkla 파일 편집\n\n$ sudo vi /etc/polkit-1/localauthority/50-local.d/color.pkla\n\n\n해당 파일에 아래 내용을 작성함.\n\n[Allow colord for all users]\nIdentity=unix-user:*\nAction=org.freedesktop.color-manager.create-device;org.freedesktop.color-manager.create-profile;org.freedesktop.color-manager.delete-device;org.freedesktop.color-manager.delete-profile;org.freedesktop.color-manager.modify-device;org.freedesktop.color-manager.modify-profile\nResultAny=yes\nResultInactive=yes\nResultActive=yes\n\n\n혹은 wget으로 해당 파일을 다운로드 받아서 복사해도 됩니다.\n\n$ wget https://raw.githubusercontent.com/boyinblue/test/main/ubuntu/color.pkla/color.pkla\n$ sudo mv color.pkla /etc/polkit-1/localauthority/50-local.d/\n\n\n관련 링크\n\n우분투 22.04에서 xrdp 연결시 색상 프로필을 만들려면 인증이 필요합니다. 라는 메시지가 뜨지 않도록 조치하는 방법\n\n이상입니다.\n"]
Title : 파이선 터틀 그래픽을 이용해서 간단한 랜덤 문자 출력 방법
URL : /004_python/002.html
Description : 파이선 터틀 그래픽을 이용하여 간단한 랜덤 문자를 출력하는 방법에 대해서 설명합니다.
Content : 지난 시간에는 파이선의 opencv를 이용해서 이미지 파일을 출력하거나,
웹캡 화면을 실시간으로 출력하는 방법에 대해서 알아보았습니다.

이번 시간에는 파이선의 터틀 그래픽을 이용해서 간단한 문자 출력 방법에 대해서 설명을 드리고,
간단한 예제를 보여드리도록 하겠습니다.

(예제1) 화면에 a, b, c를 출력하세요.

우선 터틀 그래픽을 이용해서 간단한 랜덤 문자를 출력하는 방법입니다.

import turtle
import time

def main():

turtle.setup(width=640, height=480)
turtle.write("a", True)
turtle.write("b", True)
turtle.write("c", True)

time.sleep(10)

if __name__ == '__main__':
main()


전체 스크립트는 위와 같이 간단합니다.
코드를 하나 하나씩 자세하게 설명드리겠습니다.

import turtle


터틀 그래픽을 이용하기 위해서 turtle 패키지를 import 시켰습니다.

import time


또한, 그래픽이 모두 그려진 이후에 10초간 화면이 표시될 수 있도록 하기 위해서 time 패키지를 import 시켰습니다.

turtle.setup(width=640, height=480)


main() 함수가 실행되면 화면의 크기를 가로 640, 세로 480 크기만큼 만듭니다. setup() 메소드는 터틀 그래픽이 그려진 화면의 크기를 설정합니다.

turtle.write("a", True)
turtle.write("b", True)
turtle.write("c", True)


이후에 “a”, “b”, “c” 문자를 순서대로 출력합니다.
문자열을 터틀 그래픽에 출력하기 위해서는 turtle.write(문자열, 커서 이동 여부) 메소드를 사용하면 됩니다.
두 번째 인자에 True를 입력하면 출력 후에 커서를 이동하고, False를 입력하면 출력 후에 커서 이동을 하지 않습니다.

time.sleep(10)


문자 출력이 완료되면 10초간 기다려서 그래픽 화면이 바로 닫히지 않도록 하였습니다.

(예제2) 랜덤한 문자를 10개 1초에 하나씩 출력하는 예제

이번에는 랜덤한 문자 10개를 1초에 하나씩 출력하는 예제를 살펴보겠습니다.

import turtle
import time
import random

letters = [ "a", "b", "c", "d", "e", "f", "g" ]

def main():

turtle.setup(width=640, height=480)

cnt = 0
while cnt < 10:
rand_num = random.randrange(0, len(letters))
turtle.write(letters[rand_num], True)
time.sleep(1)
cnt = cnt + 1

if __name__ == '__main__':
main()


우선 import 시킨 패키지가 하나 추가되었습니다.
바로 random 패키지입니다.

import random


출력할 문자의 리스트를 정의합니다.

letters = [ "a", "b", "c", "d", "e", "f", "g" ]


while 문을 이용해서 10회 반복을 합니다.

cnt = 0
while cnt < 10:
# Todo Something
time.sleep(1)
cnt = cnt + 1


위의 while 문은 1초에 한번씩 # Todo Something위치에 있는 코드를 수행할 것입니다.

rand_num = random.randrange(0, len(letters))


0부터 리스트의 개수만큼의 범위 안에서 랜덤값을 가져옵니다.

위의 코드는 아래의 코드와 equivalent 합니다.

rand_num = random.randrand(0, 7)


letters 리스트의 개수가 추후에 변경될 수 있으므로
리스트의 개수 만큼의 범위에서 가져올 수 있도록 하는게 좋습니다.

cnt = 0
while cnt < 10:
rand_num = random.randrange(0, len(letters))
turtle.write(letters[rand_num], True)
time.sleep(1)
cnt = cnt + 1


위와 같이 구현이 모두 완료되었습니다.

관련 글

다음은 터틀 그래픽을 이용해서 여러가지 모양들을 그려보는 예제입니다.

파이썬 터틀 그래픽 재미있는 모양 예제

결론

본 페이지에서는 터틀 그래픽과 랜덤을 이용해서 임의의 문자를 출력하는 예제에 대해서 설명드렸습니다.
["지난 시간에는 파이선의 opencv를 이용해서 이미지 파일을 출력하거나, \n웹캡 화면을 실시간으로 출력하는 방법에 대해서 알아보았습니다.\n\n이번 시간에는 파이선의 터틀 그래픽을 이용해서 간단한 문자 출력 방법에 대해서 설명을 드리고, \n간단한 예제를 보여드리도록 하겠습니다.\n\n(예제1) 화면에 a, b, c를 출력하세요.\n\n우선 터틀 그래픽을 이용해서 간단한 랜덤 문자를 출력하는 방법입니다.\n\nimport turtle\nimport time\n\ndef main():\n\n turtle.setup(width=640, height=480)\n turtle.write(\"a\", True)\n turtle.write(\"b\", True)\n turtle.write(\"c\", True)\n\n time.sleep(10)\n\nif __name__ == '__main__':\n main()\n\n\n전체 스크립트는 위와 같이 간단합니다. \n코드를 하나 하나씩 자세하게 설명드리겠습니다.\n\nimport turtle\n\n\n터틀 그래픽을 이용하기 위해서 turtle 패키지를 import 시켰습니다.\n\nimport time\n\n\n또한, 그래픽이 모두 그려진 이후에 10초간 화면이 표시될 수 있도록 하기 위해서 time 패키지를 import 시켰습니다.\n\nturtle.setup(width=640, height=480)\n\n\nmain() 함수가 실행되면 화면의 크기를 가로 640, 세로 480 크기만큼 만듭니다. setup() 메소드는 터틀 그래픽이 그려진 화면의 크기를 설정합니다.\n\nturtle.write(\"a\", True)\nturtle.write(\"b\", True)\nturtle.write(\"c\", True)\n\n\n이후에 “a”, “b”, “c” 문자를 순서대로 출력합니다. \n문자열을 터틀 그래픽에 출력하기 위해서는 turtle.write(문자열, 커서 이동 여부) 메소드를 사용하면 됩니다. \n두 번째 인자에 True를 입력하면 출력 후에 커서를 이동하고, False를 입력하면 출력 후에 커서 이동을 하지 않습니다.\n\ntime.sleep(10)\n\n\n문자 출력이 완료되면 10초간 기다려서 그래픽 화면이 바로 닫히지 않도록 하였습니다.\n\n(예제2) 랜덤한 문자를 10개 1초에 하나씩 출력하는 예제\n\n이번에는 랜덤한 문자 10개를 1초에 하나씩 출력하는 예제를 살펴보겠습니다.\n\nimport turtle\nimport time\nimport random\n\nletters = [ \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\" ]\n\ndef main():\n\n turtle.setup(width=640, height=480)\n\n cnt = 0\n while cnt < 10:\n rand_num = random.randrange(0, len(letters))\n turtle.write(letters[rand_num], True)\n time.sleep(1)\n cnt = cnt + 1\n\nif __name__ == '__main__':\n main()\n\n\n우선 import 시킨 패키지가 하나 추가되었습니다. \n바로 random 패키지입니다.\n\nimport random\n\n\n출력할 문자의 리스트를 정의합니다.\n\nletters = [ \"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\" ]\n\n\nwhile 문을 이용해서 10회 반복을 합니다.\n\ncnt = 0\nwhile cnt < 10:\n # Todo Something\n time.sleep(1)\n cnt = cnt + 1\n\n\n위의 while 문은 1초에 한번씩 # Todo Something위치에 있는 코드를 수행할 것입니다.\n\nrand_num = random.randrange(0, len(letters))\n\n\n0부터 리스트의 개수만큼의 범위 안에서 랜덤값을 가져옵니다.\n\n위의 코드는 아래의 코드와 equivalent 합니다.\n\nrand_num = random.randrand(0, 7)\n\n\nletters 리스트의 개수가 추후에 변경될 수 있으므로 \n리스트의 개수 만큼의 범위에서 가져올 수 있도록 하는게 좋습니다.\n\ncnt = 0\nwhile cnt < 10:\n rand_num = random.randrange(0, len(letters))\n turtle.write(letters[rand_num], True)\n time.sleep(1)\n cnt = cnt + 1\n\n\n위와 같이 구현이 모두 완료되었습니다.\n\n관련 글\n\n다음은 터틀 그래픽을 이용해서 여러가지 모양들을 그려보는 예제입니다.\n\n파이썬 터틀 그래픽 재미있는 모양 예제\n\n결론\n\n본 페이지에서는 터틀 그래픽과 랜덤을 이용해서 임의의 문자를 출력하는 예제에 대해서 설명드렸습니다.\n"]
Title : 워드프레스의 xmlrpc API 이용 방법
URL : /013_wordpress/001-wordpress-xmlrpc-api.html
Description : 워드프레스 자동화 방법 중의 하나인 xmlrpc API 이용 방법에 대해서 설명합니다.
Content : 많은 웹페이지들이 워드프레스로 만들어지고 있습니다.
또한, 네이버 블로그나 티스토리 같은 블로그들을 이용하던 분들 역시도
워드프레스로 많이 넘어가는 것 같습니다.

워드프레스의 강점들을 상당히 많습니다.
손쉽게 적용하고 사용할 수 있는 다양한 플러그인도 훌륭하고,
웹페이지를 자동화할 수 있는 API 역시도 활용도가 높습니다.

본 페이지에서는 워드프레스의 xmlrpc API를 이용하는 방법에 대해서 설명합니다.

워드프레스 XML-RPC API 페이지

워드프레스의 XML-RPC API에 대해서 가장 잘 정리된 페이지는
https://codex.wordpress.org/XML-RPC_WordPress_API로 접속하시면 됩니다.

사실 XML-RPC는 워드프레스의 취약점 중의 하나입니다만,
여러가지 플러그인들을 이용해서 그런 취약점을 보완할 수 있습니다.
잘만 사용한다면 웹페이지 또는 블로그의 자동화를 이뤄낼 수 있습니다.

워드프레스의 또 다른 단점이라면, 제법 무겁게 동작한다는 것입니다.
이 때문에 워드프레스 편집기로 웹페이지를 편집할 때
상당히 버벅거리는 현상을 느낄 수 있습니다.

XML-RPC API를 통해서 웹페이지를 생성하고 편집하면
이런 단점을 보완할 수 있는 훌륭한 수단이 됩니다.

포스트 글 가져오는 예제

우선 가장 간단하게 해볼 수 있는 getPost query를 수행해보겠습니다.
모든 API는 정해진 문서에서 정의한 프로토콜대로 수행해야 합니다.
우선 getPost 쿼리의 파라미터를 살펴보겠습니다.

1. getPost 파라미터




Parameter
Type
Mandotory
Description




username
string
Y
워드프레스 ID


password
string
Y
워드프레스 비밀번호


post_id
int
Y
워드프레스 글 번호


fields
array
 
 




2. Query를 위한 xml 작성

위와 같은 포맷으로 xml을 먼저 생성합니다.

<?xml version="1.0"?>
<methodCall>
<methodName>wp.getPost</methodName>
<params>
<param>
<value><string>id</string></value>
</param>
<param>
<value><string>password</string></value>
</param>
<param>
<value><int>0</int></value>
</param>
</params>
</methodCall>


필수적으로 입력해야 하는 id, password, 글번호 3개 항목만 포함시켜서
위와 같이 xml을 생성합니다.

만약 스크립트가 GitHub와 같은 형상관리 시스템을 이용하고 있다면,
스크립트에 계정 정보가 포함되지 않도록 유의하시기 바랍니다.

curl 명령을 통해서 query 전송

위와 같이 xml 파일을 생성했다면 curl 명령을 통해서 워드프레스에 전송합니다.

curl --data @getPost.xml https://웹서버주소/api/xmlrpc


위의 query에 대한 응답으로 워드프레스의 글이 리턴됩니다.

PHP의 XML 확장이 가능하지 않습니다?

만약 워드프레스에 아래와 같은 에러가 발생하고,
포스트 정보를 제대로 가져올 수 없다면
Query를 전송한 URL을 다시 한번 살펴보시기 바랍니다.


올바른 URL : curl --data @getPost.xml https://웹서버주소/api/xmlrpc
잘못된 URL : curl --data @getPost.xml https://웹서버주소/xmlrpc.php


이상으로 워드프레스의 XML RPC를 이용해서
간단한 query를 진행하는 방법에 대한 설명을 마칩니다.

이상입니다.
["많은 웹페이지들이 워드프레스로 만들어지고 있습니다. \n또한, 네이버 블로그나 티스토리 같은 블로그들을 이용하던 분들 역시도 \n워드프레스로 많이 넘어가는 것 같습니다.\n\n워드프레스의 강점들을 상당히 많습니다. \n손쉽게 적용하고 사용할 수 있는 다양한 플러그인도 훌륭하고, \n웹페이지를 자동화할 수 있는 API 역시도 활용도가 높습니다.\n\n본 페이지에서는 워드프레스의 xmlrpc API를 이용하는 방법에 대해서 설명합니다.\n\n워드프레스 XML-RPC API 페이지\n\n워드프레스의 XML-RPC API에 대해서 가장 잘 정리된 페이지는 \nhttps://codex.wordpress.org/XML-RPC_WordPress_API로 접속하시면 됩니다.\n\n사실 XML-RPC는 워드프레스의 취약점 중의 하나입니다만, \n여러가지 플러그인들을 이용해서 그런 취약점을 보완할 수 있습니다. \n잘만 사용한다면 웹페이지 또는 블로그의 자동화를 이뤄낼 수 있습니다.\n\n워드프레스의 또 다른 단점이라면, 제법 무겁게 동작한다는 것입니다. \n이 때문에 워드프레스 편집기로 웹페이지를 편집할 때 \n상당히 버벅거리는 현상을 느낄 수 있습니다.\n\nXML-RPC API를 통해서 웹페이지를 생성하고 편집하면 \n이런 단점을 보완할 수 있는 훌륭한 수단이 됩니다.\n\n포스트 글 가져오는 예제\n\n우선 가장 간단하게 해볼 수 있는 getPost query를 수행해보겠습니다. \n모든 API는 정해진 문서에서 정의한 프로토콜대로 수행해야 합니다. \n우선 getPost 쿼리의 파라미터를 살펴보겠습니다.\n\n1. getPost 파라미터\n\n\n \n \n Parameter\n Type\n Mandotory\n Description\n \n \n \n \n username\n string\n Y\n 워드프레스 ID\n \n \n password\n string\n Y\n 워드프레스 비밀번호\n \n \n post_id\n int\n Y\n 워드프레스 글 번호\n \n \n fields\n array\n  \n  \n \n \n\n\n2. Query를 위한 xml 작성\n\n위와 같은 포맷으로 xml을 먼저 생성합니다.\n\n<?xml version=\"1.0\"?>\n<methodCall>\n <methodName>wp.getPost</methodName>\n <params>\n <param>\n <value><string>id</string></value>\n </param>\n <param>\n <value><string>password</string></value>\n </param>\n <param>\n <value><int>0</int></value>\n </param>\n </params>\n</methodCall>\n\n\n필수적으로 입력해야 하는 id, password, 글번호 3개 항목만 포함시켜서 \n위와 같이 xml을 생성합니다.\n\n만약 스크립트가 GitHub와 같은 형상관리 시스템을 이용하고 있다면, \n스크립트에 계정 정보가 포함되지 않도록 유의하시기 바랍니다.\n\ncurl 명령을 통해서 query 전송\n\n위와 같이 xml 파일을 생성했다면 curl 명령을 통해서 워드프레스에 전송합니다.\n\ncurl --data @getPost.xml https://웹서버주소/api/xmlrpc\n\n\n위의 query에 대한 응답으로 워드프레스의 글이 리턴됩니다.\n\nPHP의 XML 확장이 가능하지 않습니다?\n\n만약 워드프레스에 아래와 같은 에러가 발생하고, \n포스트 정보를 제대로 가져올 수 없다면 \nQuery를 전송한 URL을 다시 한번 살펴보시기 바랍니다.\n\n\n 올바른 URL : curl --data @getPost.xml https://웹서버주소/api/xmlrpc\n 잘못된 URL : curl --data @getPost.xml https://웹서버주소/xmlrpc.php\n\n\n이상으로 워드프레스의 XML RPC를 이용해서 \n간단한 query를 진행하는 방법에 대한 설명을 마칩니다.\n\n이상입니다.\n"]
Title : 파이썬으로 워드프레스 글 자동 발행하기
URL : /004_python/008-python-wordpress-update.html
Description : 파이썬으로 워드프레스 글을 자동 발행하는 방법에 대해서 설명합니다.
Content : 패키지 설치

파이썬으로 워드프레스 글을 자동으로 발행하기 위해서는
몇가지 패키지가 설치되어 있어야 합니다.


python-wordpress-xmlrpc 패키지
php-xml 패키지


python-wordpress-xmlrpc 패키지 설치

아래의 명령으로 python-wordpress-xmlrpc 패키지를 설치합니다.

$ sudo pip3 install python-wordpress-xmlrpc


만약 pip 패키지가 설치되어 있지 않다면 아래와 같은 에러가 뜹니다.

명령어 'pip' 을(를) 찾을 수 없습니다. 그러나 다음을 통해서 설치할 수 있습니다:

sudo apt install python3-pip


만약 pip 패키지가 설치되어 있지 않다면
아래의 명령으로 python3-pip 패키지를 설치할 수 있습니다.

$ sudo apt-get install python3-pip


pip-xml 패키지 설치

아래의 명령으로 php-xml 패키지를 설치합니다.
만약 php-xml 패키지가 설치되어 있지 않으면 에러가 뜹니다.

$ sudo apt-get install php-xml


php-xml 패키지를 설치했다면 아파치 웹서비스를 재시작 해줘야 합니다.

$ sudo service apache2 restart


파이썬 스크립트 작성

아래와 같이 파이썬 스크립트를 구성하고 실행하면 됩니다.

#!/usr/bin/python3

from wordpress_xmlrpc import Client, WordPressPost
from wordpress_xmlrpc.methods import posts

def write_post(url, id, pw, title, slug, content):
print("id :", id)
print("pw :", pw)
url = url + "/xmlrpc.php"
print("url :", url)
client = Client(url, id, pw)
post = WordPressPost()
post.title = title
post.slug = slug
post.content = content
post.terms_names = {
'post_tag': 'wordpress',
'category' : ['']
}

post.post_status = 'publish'
client.call(posts.NewPost(post))

if __name__ == '__main__':
write_post( URL,
id,
pw,
"자동 글쓰기",
"자동 글쓰기 테스트",
"자동 글쓰기 본문")

["패키지 설치\n\n파이썬으로 워드프레스 글을 자동으로 발행하기 위해서는 \n몇가지 패키지가 설치되어 있어야 합니다.\n\n\n python-wordpress-xmlrpc 패키지\n php-xml 패키지\n\n\npython-wordpress-xmlrpc 패키지 설치\n\n아래의 명령으로 python-wordpress-xmlrpc 패키지를 설치합니다.\n\n$ sudo pip3 install python-wordpress-xmlrpc\n\n\n만약 pip 패키지가 설치되어 있지 않다면 아래와 같은 에러가 뜹니다.\n\n명령어 'pip' 을(를) 찾을 수 없습니다. 그러나 다음을 통해서 설치할 수 있습니다:\n\nsudo apt install python3-pip\n\n\n만약 pip 패키지가 설치되어 있지 않다면 \n아래의 명령으로 python3-pip 패키지를 설치할 수 있습니다.\n\n$ sudo apt-get install python3-pip\n\n\npip-xml 패키지 설치\n\n아래의 명령으로 php-xml 패키지를 설치합니다. \n만약 php-xml 패키지가 설치되어 있지 않으면 에러가 뜹니다.\n\n$ sudo apt-get install php-xml\n\n\nphp-xml 패키지를 설치했다면 아파치 웹서비스를 재시작 해줘야 합니다.\n\n$ sudo service apache2 restart\n\n\n파이썬 스크립트 작성\n\n아래와 같이 파이썬 스크립트를 구성하고 실행하면 됩니다.\n\n#!/usr/bin/python3\n\nfrom wordpress_xmlrpc import Client, WordPressPost\nfrom wordpress_xmlrpc.methods import posts\n\ndef write_post(url, id, pw, title, slug, content):\n print(\"id :\", id)\n print(\"pw :\", pw)\n url = url + \"/xmlrpc.php\"\n print(\"url :\", url)\n client = Client(url, id, pw)\n post = WordPressPost()\n post.title = title\n post.slug = slug\n post.content = content\n post.terms_names = {\n 'post_tag': 'wordpress',\n 'category' : ['']\n }\n\n post.post_status = 'publish'\n client.call(posts.NewPost(post))\n\nif __name__ == '__main__':\n write_post( URL,\n id,\n pw,\n \"자동 글쓰기\",\n \"자동 글쓰기 테스트\",\n \"자동 글쓰기 본문\")\n\n"]
Title : OpenCV를 이용하여 이미지를 출력하는 방법과 캠을 동작시키는 방법
URL : /004_python/001.html
Description : OpenCV를 이용해서 이미지를 출력하는 방법과 실시간으로 캠 영상을 표시 방법을 설명합니다.
Content : Ubuntu Linux와 Python 언어를 기준으로 작성되었습니다.

OpenCV를 이용해서 이미지를 출력하는 방법

아래의 짧은 파이선 스크립트로 ‘test.png’ 파일을 화면에 출력할 수 있다.
OpenCV를 사용하므로 OpenCV 패키지가 설치되어 있어야 한다.

처음에 화면이 뜨기까지는 시간이 상당히 소요된다.
사용자로부터 키 입력을 계속 받다가 ‘q’가 입력되면 프로그램이 종료되는 구조다.

예제

import cv2

if __name__ == '__main__':
img = cv2.imread('test.png')
cv2.imshow('window_name', img)

while True:
if cv2.waitKey(1) & 0xFF == ord('q'):
break

cv2.destroyAllWindows()


짧은 스크립트로 이미지 파일을 출력할 수 있다니 놀랍기만 하다.
하지만 놀라기는 아직 이르다.
아주 간단한 스크립트 몇 줄로 PC의 카메라도 동작시킬 수 있다.

OpenCV를 이용해서 캠을 동작시키는 방법

이미지 뿐만 아니라 웹캡도 동작시킬 수 있다.
이런 프로그램을 윈도우즈에서 C를 이용해서 작성하는 것이 얼마나 어려운 일인지 안다.
그 어려운 것을 파이선은 이렇게 손쉽게 할 수 있다.

예제

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

while(True):
# Capture frame-by-frame
ret, frame = cap.read()

# Display the resulting frame
cv2.imshow('frame',frame)

if cv2.waitKey(1) & 0xFF == ord('q'):
break

cv2.destroyWindow('frame')

# When everything done, release the capture
cap.release()


위와 같이 스크립트를 작성하고 실행하면 진짜로 웹캠이 실행되면서
내 못생긴 얼굴이 화면에 실시간으로 출력되기 시작한다.

인텔에서 만든 OpenCV로 할 수 있는 것은 무궁무진할 것 같다.
파이선이라는 놀라운 언어가 지금껏 하기 어려웠던 것들을 손쉽게 할 수 있도록 해준다.
놀랍고도 놀라울 따름이다.
["Ubuntu Linux와 Python 언어를 기준으로 작성되었습니다.\n\nOpenCV를 이용해서 이미지를 출력하는 방법\n\n아래의 짧은 파이선 스크립트로 ‘test.png’ 파일을 화면에 출력할 수 있다. \nOpenCV를 사용하므로 OpenCV 패키지가 설치되어 있어야 한다.\n\n처음에 화면이 뜨기까지는 시간이 상당히 소요된다. \n사용자로부터 키 입력을 계속 받다가 ‘q’가 입력되면 프로그램이 종료되는 구조다.\n\n예제\n\nimport cv2\n\nif __name__ == '__main__':\n img = cv2.imread('test.png')\n cv2.imshow('window_name', img)\n\n while True:\n if cv2.waitKey(1) & 0xFF == ord('q'):\n break\n\n cv2.destroyAllWindows()\n\n\n짧은 스크립트로 이미지 파일을 출력할 수 있다니 놀랍기만 하다. \n하지만 놀라기는 아직 이르다. \n아주 간단한 스크립트 몇 줄로 PC의 카메라도 동작시킬 수 있다.\n\nOpenCV를 이용해서 캠을 동작시키는 방법\n\n이미지 뿐만 아니라 웹캡도 동작시킬 수 있다. \n이런 프로그램을 윈도우즈에서 C를 이용해서 작성하는 것이 얼마나 어려운 일인지 안다. \n그 어려운 것을 파이선은 이렇게 손쉽게 할 수 있다.\n\n예제\n\nimport numpy as np\nimport cv2\n\ncap = cv2.VideoCapture(0)\n\nwhile(True):\n # Capture frame-by-frame\n ret, frame = cap.read()\n\n # Display the resulting frame\n cv2.imshow('frame',frame)\n\n if cv2.waitKey(1) & 0xFF == ord('q'):\n break\n\ncv2.destroyWindow('frame')\n\n# When everything done, release the capture\ncap.release()\n\n\n위와 같이 스크립트를 작성하고 실행하면 진짜로 웹캠이 실행되면서 \n내 못생긴 얼굴이 화면에 실시간으로 출력되기 시작한다.\n\n인텔에서 만든 OpenCV로 할 수 있는 것은 무궁무진할 것 같다. \n파이선이라는 놀라운 언어가 지금껏 하기 어려웠던 것들을 손쉽게 할 수 있도록 해준다. \n놀랍고도 놀라울 따름이다.\n"]
Title : mysql 컬럼 목록 조회 쿼리
URL : /_pages/mysql/2022-05-13-mysql-column-list-query.html
Description : mysql 컬럼 목록을 살펴보는 방법에 대해서 설명합니다.
Content : mysql 컬럭 목록을 간략하게 살펴보는 쿼리

show columns from TABLE_NAME; 명령을 통해서
컬럼 목록을 조회할 수 있습니다.

쿼리의 마지막은 반드시 세미콜론으로 끝나야 합니다.

mysql> show columns from wp_users;
+---------------------+-----------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+-----------------+------+-----+---------------------+----------------+
| ID | bigint unsigned | NO | PRI | NULL | auto_increment |
| user_login | varchar(60) | NO | MUL | | |
| user_pass | varchar(255) | NO | | | |
| user_nicename | varchar(50) | NO | MUL | | |
| user_email | varchar(100) | NO | MUL | | |
| user_url | varchar(100) | NO | | | |
| user_registered | datetime | NO | | 0000-00-00 00:00:00 | |
| user_activation_key | varchar(255) | NO | | | |
| user_status | int | NO | | 0 | |
| display_name | varchar(250) | NO | | | |
+---------------------+-----------------+------+-----+---------------------+----------------+
10 rows in set (0.00 sec)
---


위에서 확인한 컬럼명으로 필요한 컬럼만 골라서 출력할 수 있습니다.


### 필요한 컬럼만 조회하는 방법


```sql
mysql> select id, user_login from wp_users;
+----+------------------------+
| id | user_login |
+----+------------------------+
| 1 | esregnet0409@gmail.com |
+----+------------------------+
1 row in set (0.00 sec)


["mysql 컬럭 목록을 간략하게 살펴보는 쿼리\n\nshow columns from TABLE_NAME; 명령을 통해서 \n컬럼 목록을 조회할 수 있습니다.\n\n쿼리의 마지막은 반드시 세미콜론으로 끝나야 합니다.\n\nmysql> show columns from wp_users;\n+---------------------+-----------------+------+-----+---------------------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+---------------------+-----------------+------+-----+---------------------+----------------+\n| ID | bigint unsigned | NO | PRI | NULL | auto_increment |\n| user_login | varchar(60) | NO | MUL | | |\n| user_pass | varchar(255) | NO | | | |\n| user_nicename | varchar(50) | NO | MUL | | |\n| user_email | varchar(100) | NO | MUL | | |\n| user_url | varchar(100) | NO | | | |\n| user_registered | datetime | NO | | 0000-00-00 00:00:00 | |\n| user_activation_key | varchar(255) | NO | | | |\n| user_status | int | NO | | 0 | |\n| display_name | varchar(250) | NO | | | |\n+---------------------+-----------------+------+-----+---------------------+----------------+\n10 rows in set (0.00 sec)\n---\n\n\n위에서 확인한 컬럼명으로 필요한 컬럼만 골라서 출력할 수 있습니다. \n\n\n### 필요한 컬럼만 조회하는 방법\n\n\n```sql\nmysql> select id, user_login from wp_users;\n+----+------------------------+\n| id | user_login |\n+----+------------------------+\n| 1 | esregnet0409@gmail.com |\n+----+------------------------+\n1 row in set (0.00 sec)\n\n\n"]
Title : mySQL 기본 명령어 정리
URL : /_pages/mysql/2022-05-13-mysql-basic-query.html
Description : mySQL 기본적인 명령어를 기록해두는 페이지입니다.
Content : mySQL 설치 방법

Ubuntu Linux 기준으로 설명드립니다.

$ sudo apt-get install mysql-server mysql-client


만약 php와 연동하기 위해서는 php-mysql 패키지도 설치합니다.

$ sudo apt-get install


mySQL 서비스 동작 상태 확인

설치가 정상적으로 되었다면, 서비스가 정상적으로 돌아야 합니다.

$ sudo service mysql status


sudo service mysql status 명령을 실행했을 때,
아래와 같이 active (running)으로 상태가 표시되어야 합니다.



mySQL 콘솔 접속 방법

sudo mysql -uroot -p 명령으로 mySQL 콘솔에 접속을 합니다.
반드시 sudo 권한으로 실행해야 합니다.
그렇지 않으면 아래와 같이 ERROR 1698 (28000) 에러가 뜹니다.

$ mysql -uroot -p
Enter password:
ERROR 1698 (28000): Access denied for user 'root'@'localhost'


mySQL 콘솔에 정상적으로 접속이 되면
mysql\> 프롬프트가 표시됩니다.

SQL 쿼리시에 주의할 점

SQL 쿼리는 ;로 끝나야 합니다.
세미콜론을 입력하지 않고 엔터키를 누르면
SQL은 쿼리가 계속되는지 알고 개행된 상태로 쿼리를 계속 받게 됩니다.

이 점에 유의하시기 바랍니다.

데이터베이스 목록 조회

mysql\> 프롬프트에 show databases;를 입력하면
데이터베이스 목록을 조회할 수 있습니다.

mysql> show databases;


아래와 같이 실행 결과가 나옵니다.

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| wordpress |
+--------------------+
5 rows in set (0.01 sec)


데이베이스 선택

use 명령을 통해서 데이터베이스를 선택할 수 있습니다.
만약, wordpress라는 데이터베이스에 접속하려면
use wordpress;와 같이 명령을 실행하면 됩니다.

mysql> use wordpress;


wordpress라는 데이터베이스가 선택되었습니다.

만약 데이터베이스를 선택하지 않은 상태에서 테이블을 살펴보면,
ERROR 1046 (3D000) 에러가 발생하게 됩니다.

mysql> show tables;
ERROR 1046 (3D000): No database selected


테이블을 출력하는 쿼리

사용할 DB를 선택했다면, 이번에는 테이블 목록을 살펴볼 차례입니다.

show tables; 명령으로 데이터베이스 내부에
어떤 테이블들이 있는지 살펴볼 차례입니다.

mysql> show tables;
+-----------------------+
| Tables_in_wordpress |
+-----------------------+
| wp_commentmeta |
| wp_comments |
| wp_links |
| wp_options |
| wp_postmeta |
| wp_posts |
| wp_term_relationships |
| wp_term_taxonomy |
| wp_termmeta |
| wp_terms |
| wp_usermeta |
| wp_users |
+-----------------------+
12 rows in set (0.01 sec)


위와 같이 데이터베이스 내부의 테이블들이 표시됩니다.

테이블의 모든 내용을 출력하는 명령

가장 기본이되는 select 명령이 등장할 차례입니다.

mysql> select * from wp_users;
+----+------------------------+------------------------------------+-----------------------+-----------------------+----------------------------+---------------------+---------------------+-------------+------------------------+
| ID | user_login | user_pass | user_nicename | user_email | user_url | user_registered | user_activation_key | user_status | display_name |
+----+------------------------+------------------------------------+-----------------------+-----------------------+----------------------------+---------------------+---------------------+-------------+------------------------+
| 1 | esregnet0409@gmail.com | ################################## | esregnet0409gmail-com | esrgnet0409@gmail.com | https://www.dhqhrtnwl.shop | 2022-05-12 07:14:10 | | 0 | esregnet0409@gmail.com |
+----+------------------------+------------------------------------+-----------------------+-----------------------+----------------------------+---------------------+---------------------+-------------+------------------------+
1 row in set (0.01 sec)


모든 데이터가 출력되기 때문에 필요한 항목들만 선택해서 출력할 수 있습니다.

컬럼을 조회하는 쿼리

show columns from wp_users; 쿼리를 통해서
컬럼 정보를 조회할 수 있습니다.

mysql> show columns from wp_users;
+---------------------+-----------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+-----------------+------+-----+---------------------+----------------+
| ID | bigint unsigned | NO | PRI | NULL | auto_increment |
| user_login | varchar(60) | NO | MUL | | |
| user_pass | varchar(255) | NO | | | |
| user_nicename | varchar(50) | NO | MUL | | |
| user_email | varchar(100) | NO | MUL | | |
| user_url | varchar(100) | NO | | | |
| user_registered | datetime | NO | | 0000-00-00 00:00:00 | |
| user_activation_key | varchar(255) | NO | | | |
| user_status | int | NO | | 0 | |
| display_name | varchar(250) | NO | | | |
+---------------------+-----------------+------+-----+---------------------+----------------+
10 rows in set (0.01 sec)


특정 항목만 선택해서 출력하는 쿼리

위에서 조회한 컬럼 목록에서 필요한 항목들만 선택해서 조회할 수 있습니다.

select user_login, user_email from wp_users; 명령처럼
필요한 항목들만 선택해서 출력도 가능합니다.

mysql> select user_login, user_email from wp_users;
+------------------------+-----------------------+
| user_login | user_email |
+------------------------+-----------------------+
| esregnet0409@gmail.com | esrgnet0409@gmail.com |
+------------------------+-----------------------+
1 row in set (0.00 sec)


테이블 수정하는 방법

위의 레코드에서 user_email 항목에 오타가 발견되었습니다.
수정을 위해서는 update 쿼리를 사용하면 됩니다.

mysql> update wp_users set user_email = "esregnet0409@gmail.com"
-> where user_email = "esrgnet0409@gmail.com";
Query OK, 1 row affected (0.07 sec)


세미콜론을 입력하지 않으면 쿼리를 계속 입력할 수 있기 때문에
쿼리가 길어질 때는 여러줄로 표시할 수 있어서 편리합니다.

다시 select 구문을 사용하여
제대로 업데이트 되었는지 확인합니다.

mysql> select user_login, user_email from wp_users;


mySQL 콘솔 종료 방법

quit; 명령을 입력하면 mySQL 콘솔을 종료시킬 수 있습니다.
["mySQL 설치 방법\n\nUbuntu Linux 기준으로 설명드립니다.\n\n$ sudo apt-get install mysql-server mysql-client\n\n\n만약 php와 연동하기 위해서는 php-mysql 패키지도 설치합니다.\n\n$ sudo apt-get install \n\n\nmySQL 서비스 동작 상태 확인\n\n설치가 정상적으로 되었다면, 서비스가 정상적으로 돌아야 합니다.\n\n$ sudo service mysql status\n\n\nsudo service mysql status 명령을 실행했을 때, \n아래와 같이 active (running)으로 상태가 표시되어야 합니다.\n\n\n\nmySQL 콘솔 접속 방법\n\nsudo mysql -uroot -p 명령으로 mySQL 콘솔에 접속을 합니다. \n반드시 sudo 권한으로 실행해야 합니다. \n그렇지 않으면 아래와 같이 ERROR 1698 (28000) 에러가 뜹니다.\n\n$ mysql -uroot -p\nEnter password: \nERROR 1698 (28000): Access denied for user 'root'@'localhost'\n\n\nmySQL 콘솔에 정상적으로 접속이 되면 \nmysql\\> 프롬프트가 표시됩니다.\n\nSQL 쿼리시에 주의할 점\n\nSQL 쿼리는 ;로 끝나야 합니다.\n세미콜론을 입력하지 않고 엔터키를 누르면 \nSQL은 쿼리가 계속되는지 알고 개행된 상태로 쿼리를 계속 받게 됩니다.\n\n이 점에 유의하시기 바랍니다.\n\n데이터베이스 목록 조회\n\nmysql\\> 프롬프트에 show databases;를 입력하면 \n데이터베이스 목록을 조회할 수 있습니다.\n\nmysql> show databases;\n\n\n아래와 같이 실행 결과가 나옵니다.\n\nmysql> show databases;\n+--------------------+\n| Database |\n+--------------------+\n| information_schema |\n| mysql |\n| performance_schema |\n| sys |\n| wordpress |\n+--------------------+\n5 rows in set (0.01 sec)\n\n\n데이베이스 선택\n\nuse 명령을 통해서 데이터베이스를 선택할 수 있습니다. \n만약, wordpress라는 데이터베이스에 접속하려면 \nuse wordpress;와 같이 명령을 실행하면 됩니다.\n\nmysql> use wordpress;\n\n\nwordpress라는 데이터베이스가 선택되었습니다.\n\n만약 데이터베이스를 선택하지 않은 상태에서 테이블을 살펴보면, \nERROR 1046 (3D000) 에러가 발생하게 됩니다.\n\nmysql> show tables;\nERROR 1046 (3D000): No database selected\n\n\n테이블을 출력하는 쿼리\n\n사용할 DB를 선택했다면, 이번에는 테이블 목록을 살펴볼 차례입니다.\n\nshow tables; 명령으로 데이터베이스 내부에 \n어떤 테이블들이 있는지 살펴볼 차례입니다.\n\nmysql> show tables;\n+-----------------------+\n| Tables_in_wordpress |\n+-----------------------+\n| wp_commentmeta |\n| wp_comments |\n| wp_links |\n| wp_options |\n| wp_postmeta |\n| wp_posts |\n| wp_term_relationships |\n| wp_term_taxonomy |\n| wp_termmeta |\n| wp_terms |\n| wp_usermeta |\n| wp_users |\n+-----------------------+\n12 rows in set (0.01 sec)\n\n\n위와 같이 데이터베이스 내부의 테이블들이 표시됩니다.\n\n테이블의 모든 내용을 출력하는 명령\n\n가장 기본이되는 select 명령이 등장할 차례입니다.\n\nmysql> select * from wp_users;\n+----+------------------------+------------------------------------+-----------------------+-----------------------+----------------------------+---------------------+---------------------+-------------+------------------------+\n| ID | user_login | user_pass | user_nicename | user_email | user_url | user_registered | user_activation_key | user_status | display_name |\n+----+------------------------+------------------------------------+-----------------------+-----------------------+----------------------------+---------------------+---------------------+-------------+------------------------+\n| 1 | esregnet0409@gmail.com | ################################## | esregnet0409gmail-com | esrgnet0409@gmail.com | https://www.dhqhrtnwl.shop | 2022-05-12 07:14:10 | | 0 | esregnet0409@gmail.com |\n+----+------------------------+------------------------------------+-----------------------+-----------------------+----------------------------+---------------------+---------------------+-------------+------------------------+\n1 row in set (0.01 sec)\n\n\n모든 데이터가 출력되기 때문에 필요한 항목들만 선택해서 출력할 수 있습니다.\n\n컬럼을 조회하는 쿼리\n\n show columns from wp_users; 쿼리를 통해서 \n컬럼 정보를 조회할 수 있습니다.\n\nmysql> show columns from wp_users;\n+---------------------+-----------------+------+-----+---------------------+----------------+\n| Field | Type | Null | Key | Default | Extra |\n+---------------------+-----------------+------+-----+---------------------+----------------+\n| ID | bigint unsigned | NO | PRI | NULL | auto_increment |\n| user_login | varchar(60) | NO | MUL | | |\n| user_pass | varchar(255) | NO | | | |\n| user_nicename | varchar(50) | NO | MUL | | |\n| user_email | varchar(100) | NO | MUL | | |\n| user_url | varchar(100) | NO | | | |\n| user_registered | datetime | NO | | 0000-00-00 00:00:00 | |\n| user_activation_key | varchar(255) | NO | | | |\n| user_status | int | NO | | 0 | |\n| display_name | varchar(250) | NO | | | |\n+---------------------+-----------------+------+-----+---------------------+----------------+\n10 rows in set (0.01 sec)\n\n\n특정 항목만 선택해서 출력하는 쿼리\n\n위에서 조회한 컬럼 목록에서 필요한 항목들만 선택해서 조회할 수 있습니다.\n\nselect user_login, user_email from wp_users; 명령처럼 \n필요한 항목들만 선택해서 출력도 가능합니다.\n\nmysql> select user_login, user_email from wp_users;\n+------------------------+-----------------------+\n| user_login | user_email |\n+------------------------+-----------------------+\n| esregnet0409@gmail.com | esrgnet0409@gmail.com |\n+------------------------+-----------------------+\n1 row in set (0.00 sec)\n\n\n테이블 수정하는 방법\n\n위의 레코드에서 user_email 항목에 오타가 발견되었습니다. \n수정을 위해서는 update 쿼리를 사용하면 됩니다.\n\nmysql> update wp_users set user_email = \"esregnet0409@gmail.com\"\n -> where user_email = \"esrgnet0409@gmail.com\";\nQuery OK, 1 row affected (0.07 sec)\n\n\n세미콜론을 입력하지 않으면 쿼리를 계속 입력할 수 있기 때문에 \n쿼리가 길어질 때는 여러줄로 표시할 수 있어서 편리합니다.\n\n다시 select 구문을 사용하여 \n제대로 업데이트 되었는지 확인합니다.\n\nmysql> select user_login, user_email from wp_users;\n\n\nmySQL 콘솔 종료 방법\n\nquit; 명령을 입력하면 mySQL 콘솔을 종료시킬 수 있습니다.\n"]
Title : 우분투 리눅스에서 NetworkManager로 IP 설정 방법
URL : /008_ubuntu/009-ubuntu-network-manager-ip-setting.html
Description : 우분투 리눅스에서 IP를 설정하는 방법은 3가지가 있습니다. 그 중에서도 NetworkManager로 IP를 설정하는 방법에 대해서 설명합니다.
Content : 가장 기본이되는 IP 설정 방법은 netplan 입니다.
만약 netplan이 아닌 NetworkManager로 IP를 설정하기 위해서는
netplan 설정파일 수정이 필요합니다.

$ sudo vi /etc/netplan/01-network-manager-all.yaml


아래와 같이 설정해줍니다.

# Let NetworkManager manage all devices on this system
network:
version: 2
renderer: NetworkManager

["가장 기본이되는 IP 설정 방법은 netplan 입니다. \n만약 netplan이 아닌 NetworkManager로 IP를 설정하기 위해서는\nnetplan 설정파일 수정이 필요합니다.\n\n$ sudo vi /etc/netplan/01-network-manager-all.yaml\n\n\n아래와 같이 설정해줍니다.\n\n# Let NetworkManager manage all devices on this system\nnetwork:\n version: 2\n renderer: NetworkManager\n\n"]
Title : vim 띄워쓰기 설정 방법
URL : /008_ubuntu/007-how-to-vim-setting.html
Description : vim 패키지 설치 방법과 띄워쓰기 설정 방법
Content : Ubuntu Linux를 처음 설치하게 되면 기본적으로 vi 에디터를 사용 가능하다.
리눅스를 오래동안 사용해온 필자에게도 vi 사용은 제법 불편하다.

특히, 키보드의 방향키가 제대로 동작하지 않는다.
그 이유는 기본적인 vi의 경우 방향키 대신에 ‘h’, ‘j’, ‘k’, ‘l’ 등의 키로
커서를 이동시키도록 되어 있기 때문이다.

vi 방향키


‘h’ : 왼쪽으로 이동
‘j’ : 아래로 이동
‘k’ : 위로 이동
‘l’ : 오른쪽으로 이동


vim 패키지를 설치하면 방향키를 사용할 수 있기 때문에
꼭 vim 패키지를 설치하시기를 강력하게 추천한다.

$ sudo apt-get install vim

vim 패키지를 설치한 이후에 vi 편집기를 열면
키보드의 방향키가 정상적으로 잘 인식되는 것을 알 수 있다.

코딩 컨벤션과 띄워쓰기

SW 개발자나 FW 개발자에게 띄워쓰기는 아주 중요하다.
하나의 프로젝트를 여러 사람들이 동시에 협업을 하다보면,
사람마다 코딩 스타일이 다르기 때문에 상당히 성가신 경우가 많다.

예를 들면, C언어에서 중괄호를 어떻게 사용할 것인가부터 시작해서,
텝(Tab)을 허용할 것인지, 텝을 허용한다면 공백을 몇개로 할 것인지 등
개발자마다 선호하는 스타일이 다르기 때문에
코딩 컨벤션이라는 것을 만들어서 비슷한 형식으로 코딩을 하도록
유도하는 회사들도 있다.

특히 파이썬 언어의 경우 공백 자체가 문법의 일부이고,
이 부분을 상당히 민감하게 체크하기 때문에
더욱 더 공백(indent)가 중요하다고 할 수 있다.

파이썬 vim 띄워쓰기 설정 방법에 대해서 관심있다면,
파이썬 vim 띄워쓰기 설정 방법 글을 참조하시기 바란다.

vim 띄워쓰기 설정을 통해서 아래의 설정들이 가능하다.


텝을 허용할 것인가?
텝을 허용한다면 몇 글자를 띄울 것인가?
텝을 공백으로 변환한다면 공백 몇개로 할 것인가?


위와 같은 설정은 vim 실행 중에 명령을 통해서도 가능하고,
설정 파일에 담게 되면 vim을 실행할때마다 자동으로 설정되도록 할 수도 있다.
또한, 언어에 따라서 다르게 설정도 가능하다.

vim 설정파일 예시

선호하는 편집기로 ~/.vimrc 파일을 편집한다.

$ vi ~/.vimrc


syntax on
filetype indent plugin on
set tabstop=4
set expandtab!
set softtabstop=4
set nu

let g:python_recommended_style=0


위의 설정은 필자가 선호하는 vim 설정이다.
그런데 다소 이해가 되지 않는 부분이 있을 것이다.

파이썬에서는 Tab을 Space로
변경해주는 것이 핵심이라고 하면서
set expandtab! 설정을 통해서
오히려 텝을 스페이스로 바꿔주지 않도록 하고 있다.

필자는 기본적으로 C언어 작업과 파이썬을 병행한다.
또한 C언어로 코딩할때 텝은 4칸을 선호한다.

따라서 필자가 C언어로 코딩할때는 텝을 그대로 사용 가능하고,
텝은 공백 4칸으로 설정이 된다.

반면, 파이썬으로 코딩할때는 아래 구문에 의해서
텝이 자동으로 스페이스로 변환된다.

let g:python_recommended_style=0

위의 코드 이전에 설정한 값들이
let g:python_recommended_style=0 설정에 의해서
overwrite될 수 있음을 유의한다.

예를들면, set expand tab!과 같은 설정은
python 스크립트 편집시에는 전혀 먹히지 않는다는 것이다.

python syntax 파일 다운로드 방법

python syntax 파일은 아래 위치에서 다운로드 받을 수 있다.

https://www.vim.org/scripts/script.php?script_id=790

python.vim 파일은 ~/.vim/syntax 경로에 저장하면 된다.

위의 페이지에 접속하는게 번거롭다면 아래 링크에서 다운로드 받으면 된다.

python.vim

아래의 명령으로 한 번에 다운로드가 가능하다.

$ mkdir -p ~/.vim/syntax
$ wget -O ~/.vim/syntax/syntax.vim https://boyinblue.github.io/004_python/python.vim


결론

파이썬은 띄워쓰기에 아주 민감한 언어이다.
그 이유는 파이썬에서의 씌워쓰기는 문법의 일부이기 때문이다.

vim에서 파이썬 스크립트를 편리하게 편집하기 위한
설정 방법에 대해서도 언급하였다.
["Ubuntu Linux를 처음 설치하게 되면 기본적으로 vi 에디터를 사용 가능하다. \n리눅스를 오래동안 사용해온 필자에게도 vi 사용은 제법 불편하다.\n\n특히, 키보드의 방향키가 제대로 동작하지 않는다. \n그 이유는 기본적인 vi의 경우 방향키 대신에 ‘h’, ‘j’, ‘k’, ‘l’ 등의 키로\n커서를 이동시키도록 되어 있기 때문이다.\n\nvi 방향키\n\n\n ‘h’ : 왼쪽으로 이동\n ‘j’ : 아래로 이동\n ‘k’ : 위로 이동\n ‘l’ : 오른쪽으로 이동\n\n\nvim 패키지를 설치하면 방향키를 사용할 수 있기 때문에 \n꼭 vim 패키지를 설치하시기를 강력하게 추천한다.\n\n$ sudo apt-get install vim\n\nvim 패키지를 설치한 이후에 vi 편집기를 열면 \n키보드의 방향키가 정상적으로 잘 인식되는 것을 알 수 있다.\n\n코딩 컨벤션과 띄워쓰기\n\nSW 개발자나 FW 개발자에게 띄워쓰기는 아주 중요하다. \n하나의 프로젝트를 여러 사람들이 동시에 협업을 하다보면, \n사람마다 코딩 스타일이 다르기 때문에 상당히 성가신 경우가 많다.\n\n예를 들면, C언어에서 중괄호를 어떻게 사용할 것인가부터 시작해서, \n텝(Tab)을 허용할 것인지, 텝을 허용한다면 공백을 몇개로 할 것인지 등 \n개발자마다 선호하는 스타일이 다르기 때문에 \n코딩 컨벤션이라는 것을 만들어서 비슷한 형식으로 코딩을 하도록 \n유도하는 회사들도 있다.\n\n특히 파이썬 언어의 경우 공백 자체가 문법의 일부이고, \n이 부분을 상당히 민감하게 체크하기 때문에 \n더욱 더 공백(indent)가 중요하다고 할 수 있다.\n\n파이썬 vim 띄워쓰기 설정 방법에 대해서 관심있다면, \n파이썬 vim 띄워쓰기 설정 방법 글을 참조하시기 바란다.\n\nvim 띄워쓰기 설정을 통해서 아래의 설정들이 가능하다.\n\n\n 텝을 허용할 것인가?\n 텝을 허용한다면 몇 글자를 띄울 것인가?\n 텝을 공백으로 변환한다면 공백 몇개로 할 것인가?\n\n\n위와 같은 설정은 vim 실행 중에 명령을 통해서도 가능하고, \n설정 파일에 담게 되면 vim을 실행할때마다 자동으로 설정되도록 할 수도 있다. \n또한, 언어에 따라서 다르게 설정도 가능하다.\n\nvim 설정파일 예시\n\n선호하는 편집기로 ~/.vimrc 파일을 편집한다.\n\n$ vi ~/.vimrc\n\n\nsyntax on\nfiletype indent plugin on\nset tabstop=4\nset expandtab!\nset softtabstop=4\nset nu\n\nlet g:python_recommended_style=0\n\n\n위의 설정은 필자가 선호하는 vim 설정이다. \n그런데 다소 이해가 되지 않는 부분이 있을 것이다.\n\n파이썬에서는 Tab을 Space로 \n변경해주는 것이 핵심이라고 하면서 \nset expandtab! 설정을 통해서 \n오히려 텝을 스페이스로 바꿔주지 않도록 하고 있다.\n\n필자는 기본적으로 C언어 작업과 파이썬을 병행한다. \n또한 C언어로 코딩할때 텝은 4칸을 선호한다.\n\n따라서 필자가 C언어로 코딩할때는 텝을 그대로 사용 가능하고, \n텝은 공백 4칸으로 설정이 된다.\n\n반면, 파이썬으로 코딩할때는 아래 구문에 의해서 \n텝이 자동으로 스페이스로 변환된다.\n\nlet g:python_recommended_style=0\n\n위의 코드 이전에 설정한 값들이 \nlet g:python_recommended_style=0 설정에 의해서 \noverwrite될 수 있음을 유의한다.\n\n예를들면, set expand tab!과 같은 설정은 \npython 스크립트 편집시에는 전혀 먹히지 않는다는 것이다.\n\npython syntax 파일 다운로드 방법\n\npython syntax 파일은 아래 위치에서 다운로드 받을 수 있다.\n\nhttps://www.vim.org/scripts/script.php?script_id=790\n\npython.vim 파일은 ~/.vim/syntax 경로에 저장하면 된다.\n\n위의 페이지에 접속하는게 번거롭다면 아래 링크에서 다운로드 받으면 된다.\n\npython.vim\n\n아래의 명령으로 한 번에 다운로드가 가능하다.\n\n$ mkdir -p ~/.vim/syntax\n$ wget -O ~/.vim/syntax/syntax.vim https://boyinblue.github.io/004_python/python.vim\n\n\n결론\n\n파이썬은 띄워쓰기에 아주 민감한 언어이다. \n그 이유는 파이썬에서의 씌워쓰기는 문법의 일부이기 때문이다.\n\nvim에서 파이썬 스크립트를 편리하게 편집하기 위한 \n설정 방법에 대해서도 언급하였다.\n"]
Title : 파이썬에서 MP3 파일 비동기 재생 방법 (playsound async)
URL : /004_python/007-python-playsound.html
Description : 파이썬에서 MP3 파일 재생 방법과 playsound를 통해 비동기 재생 방식에 대해서 설명합니다.
Content : playsound 패키지

파이썬으로 MP3 파일을 재생하는 방법은 다양합니다.
그 중에서도 playsound 패키지를 이용하면
단 한 줄로 MP3 파일을 재생할 수 있습니다.
(import 구문까지 포함하면 2 줄이면 충분합니다.)

playsound 패키지 설치하기

sudo pip3 install playsound 명령으로
playsound 패키지를 설치합니다.

$ sudo pip3 install playsound


위와 같이 playsound를 설치하면
아래 위치에 playsound.py 파일이 생성됩니다.

$ ls /usr/local/lib/python3.9/dist-packages/playsound.py -all
-rw-r--r-- 1 root root 9466 Apr 15 20:33 /usr/local/lib/python3.9/dist-packages/playsound.py


playsound로 MP3 파일 재생하기

아래는 playsound로 MP3 파일을 재생하는 간단한 예제입니다.

import playsound

playsound.playsound("sample.mp3")


놀랍게도 한 줄로 mp3 파일을 재생시킬 수 있습니다.
(import 구문까지 포함해도 2 줄로 재생이 가능합니다.)

하지만 해당 함수는 치명적인(?) 단점을 가지고 있습니다.
해당 함수는 파일 재생이 완료될 때까지 리턴을 하지 않기 때문에
중간에 재생을 정지할 수도 없고, 재생이 끝날때까지 꼼짝없이
기다리고 있어야 합니다.

이 이유는 해당 함수가 동기화된 리턴 방식(syncronized return)으로
동작하기 때문입니다.
다른 표현으로 블로킹(blocking)이라고도 표현합니다.

MP3 파일을 재생하는 도중에 다른 처리를 하기 위해서는
playsound를 async 방식(non blocking 방식)으로 처리해야 합니다.

playsound로 MP3 파일 재생하기 (ASYNC 방식)

playsound가 백그라운드(background)에서 동작하기 위해서는
함수 호출시에 non blocking 옵션을 지정하면 됩니다.

import playsound
import time

playsound.playsound("sample.mp3", block=False)
time.sleep(5)


위의 playsound.playsound("sample.mp3", block=False) 구문은
실행과 동시에 리턴이 됩니다.

실행과 동시에 리턴이 되고, 파이썬 스크립트가 종료될 수 있기 때문에
time.sleep(5)을 이용해서 MP3 파일 재생이 완료될 때까지 기다립니다.

이번 예제를 통해서 백그라운드에서 MP3 파일을 재생시킬 수는 있지만,
playsound는 치명적인(?) 단점을 가지고 있습니다.

한 번 파일을 재생시키게 되면, 파일 재생을 정지시킬 방법이 없습니다.
playsound는 MP3 파일 재생 이외의 제어는 전혀 불가능합니다.

playsound 패키지에 포함된 playsound.py 파일을 살펴보면
playsound() 메소드 이에외 어떤 함수도 없다는 것을
확인하실 수 있습니다.

playsound로 MP3 파일 재생하기 (Thread 방식)

비동기 방식으로 MP3 파일을 재생하는 또 다른 방법은
쓰레드를 이용하는 방법입니다.

import playsound
import threading
import ctypes
import time

play_thread = None

def stop_mp3():
global play_thread

if not play_thread:
return

thread_id = None
if hasattr(play_thread, '_thread_id'):
thread_id = play_thead._thread_id
else:
for id, thread in threading._active.items():
print("thread :", id, thread)
if thread is play_thread:
thread_id = id
break

print("Try to thread exit :", thread_id)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,
ctypes.py_object(SystemExit))
if res > 1:
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)
print('Exception raise failure')

def play_mp3(filename):
global play_thread

stop_mp3()

play_thread = threading.Thread(target=playsound.playsound,
args=(filename,), daemon=True)
play_thread.start()

def main():
while True:
cmd = input("cmd :")
play_mp3("sample.mp3")

if __name__ == '__main__':
main()


위의 파이썬 스크립트는 MP3 파일 재생시에 쓰레드를 이용합니다.

play_thread = threading.Thread(target=playsound.playsound,
args=(filename,), daemon=True)


threading.Thread() 구문을 통해서 쓰레드를 생성하여
MP3 파일을 재생하도록 하였습니다.

또한, 재생 이전에 기존에 생성한 쓰레드가 있다면,
기존 쓰레드를 종료시키는 코드가 포함되어 있습니다.

하지만 이 역시도 제대로 동작하지 않습니다.
그 이유는 Ubuntu Linux에서 playsound 패키지는 내부적으로
GStreamer를 이용하는데,
Ctrl + C를 입력해도 종료가 되지 않습니다.

playsound로 MP3 파일 재생하기 (Thread 방식)
["playsound 패키지\n\n파이썬으로 MP3 파일을 재생하는 방법은 다양합니다. \n그 중에서도 playsound 패키지를 이용하면 \n단 한 줄로 MP3 파일을 재생할 수 있습니다. \n(import 구문까지 포함하면 2 줄이면 충분합니다.)\n\nplaysound 패키지 설치하기\n\nsudo pip3 install playsound 명령으로 \nplaysound 패키지를 설치합니다.\n\n$ sudo pip3 install playsound\n\n\n위와 같이 playsound를 설치하면 \n아래 위치에 playsound.py 파일이 생성됩니다.\n\n$ ls /usr/local/lib/python3.9/dist-packages/playsound.py -all\n-rw-r--r-- 1 root root 9466 Apr 15 20:33 /usr/local/lib/python3.9/dist-packages/playsound.py\n\n\nplaysound로 MP3 파일 재생하기\n\n아래는 playsound로 MP3 파일을 재생하는 간단한 예제입니다.\n\nimport playsound\n\nplaysound.playsound(\"sample.mp3\")\n\n\n놀랍게도 한 줄로 mp3 파일을 재생시킬 수 있습니다. \n(import 구문까지 포함해도 2 줄로 재생이 가능합니다.)\n\n하지만 해당 함수는 치명적인(?) 단점을 가지고 있습니다. \n해당 함수는 파일 재생이 완료될 때까지 리턴을 하지 않기 때문에 \n중간에 재생을 정지할 수도 없고, 재생이 끝날때까지 꼼짝없이 \n기다리고 있어야 합니다.\n\n이 이유는 해당 함수가 동기화된 리턴 방식(syncronized return)으로 \n동작하기 때문입니다. \n다른 표현으로 블로킹(blocking)이라고도 표현합니다.\n\nMP3 파일을 재생하는 도중에 다른 처리를 하기 위해서는 \nplaysound를 async 방식(non blocking 방식)으로 처리해야 합니다.\n\nplaysound로 MP3 파일 재생하기 (ASYNC 방식)\n\nplaysound가 백그라운드(background)에서 동작하기 위해서는 \n함수 호출시에 non blocking 옵션을 지정하면 됩니다.\n\nimport playsound\nimport time\n\nplaysound.playsound(\"sample.mp3\", block=False)\ntime.sleep(5)\n\n\n위의 playsound.playsound(\"sample.mp3\", block=False) 구문은 \n실행과 동시에 리턴이 됩니다.\n\n실행과 동시에 리턴이 되고, 파이썬 스크립트가 종료될 수 있기 때문에 \ntime.sleep(5)을 이용해서 MP3 파일 재생이 완료될 때까지 기다립니다.\n\n이번 예제를 통해서 백그라운드에서 MP3 파일을 재생시킬 수는 있지만, \nplaysound는 치명적인(?) 단점을 가지고 있습니다.\n\n한 번 파일을 재생시키게 되면, 파일 재생을 정지시킬 방법이 없습니다. \nplaysound는 MP3 파일 재생 이외의 제어는 전혀 불가능합니다.\n\nplaysound 패키지에 포함된 playsound.py 파일을 살펴보면 \nplaysound() 메소드 이에외 어떤 함수도 없다는 것을 \n확인하실 수 있습니다.\n\nplaysound로 MP3 파일 재생하기 (Thread 방식)\n\n비동기 방식으로 MP3 파일을 재생하는 또 다른 방법은 \n쓰레드를 이용하는 방법입니다.\n\nimport playsound\nimport threading\nimport ctypes\nimport time\n\nplay_thread = None\n\ndef stop_mp3():\n global play_thread\n\n if not play_thread:\n return\n\n thread_id = None\n if hasattr(play_thread, '_thread_id'):\n thread_id = play_thead._thread_id\n else:\n for id, thread in threading._active.items():\n print(\"thread :\", id, thread)\n if thread is play_thread:\n thread_id = id\n break\n\n print(\"Try to thread exit :\", thread_id)\n res = ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id,\n ctypes.py_object(SystemExit))\n if res > 1:\n ctypes.pythonapi.PyThreadState_SetAsyncExc(thread_id, 0)\n print('Exception raise failure')\n\ndef play_mp3(filename):\n global play_thread\n\n stop_mp3()\n\n play_thread = threading.Thread(target=playsound.playsound, \n args=(filename,), daemon=True)\n play_thread.start()\n\ndef main():\n while True:\n cmd = input(\"cmd :\")\n play_mp3(\"sample.mp3\")\n\nif __name__ == '__main__':\n main()\n\n\n위의 파이썬 스크립트는 MP3 파일 재생시에 쓰레드를 이용합니다.\n\nplay_thread = threading.Thread(target=playsound.playsound,\nargs=(filename,), daemon=True)\n\n\nthreading.Thread() 구문을 통해서 쓰레드를 생성하여 \nMP3 파일을 재생하도록 하였습니다.\n\n또한, 재생 이전에 기존에 생성한 쓰레드가 있다면, \n기존 쓰레드를 종료시키는 코드가 포함되어 있습니다.\n\n하지만 이 역시도 제대로 동작하지 않습니다. \n그 이유는 Ubuntu Linux에서 playsound 패키지는 내부적으로 \nGStreamer를 이용하는데, \nCtrl + C를 입력해도 종료가 되지 않습니다.\n\nplaysound로 MP3 파일 재생하기 (Thread 방식)\n"]
Title : C언어에서 2차원 배열 포인터 사용 방법
URL : /012_c/001-2-dimension-array-pointer.html
Description : C언어에서 2차원 배열 포인터를 사용하는 방법에 대해서 설명합니다.
Content : 2차원 배열 포인터란?

C언어를 처음 배우는 사람들에게 가장 어려운 부분이 포인터입니다.
단일 변수의 포인터는 큰 어려움이 없습니다.
배열 포인터나 함수 포인터 등을 접하기 시작하면 굉장히 복잡하고 헷갈립니다.

특히, 배열 포인터와 포인터 배열은 혼동하기 쉽습니다.

1. 2차원 배열 선언

2차원 배열 포인터에 대해서 설명하기에 앞서서, 2차원 배열을 먼저 살펴봅시다.

int a[2][3] = { 100, 101, 102, 103, 104, 105 };

위의 코드를 통해서 우리는 2차원 배열을 선언하고, 사용할 수 있습니다.




 
Col #0
Col #1
Col #2




Row #0
100
101
102


Row #1
103
104
105




2차원 배열을 액세스 하는 것은 아주 쉽습니다.

2. 2차원 배열 포인터 선언

2차원 배열을 가리키는 포인터는 어떻게 선언해야 할까요?

void main(void)
{
int arr[2][3] = { 100, 101, 102, 103, 104, 105 };

int (*p)[3] = arr;

printf("%d", p[1][2]);
}


소스 코드

int arr[2][3];을 int (*p)[3];과 같은 형식으로 변환해주면 됩니다.

프로그래밍 언어를 배우는 많은 사람들이
문법을 왜 그렇게 만들었는지 그 이유에 대해서 궁금해하곤 합니다.

우리가 영어를 배우면서 영어 문법을 배울때, 문법을 왜 그렇게 만들었는지에 대해서
묻고 따지지 않는 것처럼 프로그래밍 언어 역시도 문법을 그렇게 정해놨기 때문에
“문법을 왜 이렇게 만들어 놨지?”라고 의문을 가지는 것은 큰 의미가 없습니다.

그저 정해진 문법을 익히고 그에 맞게 구현해야 합니다.

3. 2차원 배열 포인터를 함수 포인터로 넘기는 방법

하지만 위의 배열의 포인터를 함수 인자로 넘겨야 한다면 어떻게 해야 할까요?

void dump_data( int iRows, int iCols, int (*arr)[3] )
{
int i = 0;
int j = 0;

for ( i = 0 ; i < iRows ; i++ )
{
for ( j = 0 ; j < iCols ; j++ )
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}

void main(void)
{
int arr[2][3] = { 100, 101, 102, 103, 104, 105 };

dump_data( 2, 3, arr);
}


소스 코드

위와 같이 작성하고 빌드해서 실행하면 아래와 같은 결과가 나옵니다.

100 101 102
103 104 105


2차원 배열 포인터를 활용한 간단한 예제

#include <stdio.h>
#define MAX_STU 100
#define MAX_COURSE 10
#define MAX_NAME_SIZE 10

void temp_score(int nstu, int ncrs, int s[MAX_STU][MAX_COURSE+2],int ss[MAX_STU]){
for (int i = 0; i < nstu; i++) {
for (int j = 0; j < (nstu - 1) - i; j++) {
if (ss[j] < ss[j + 1]) {

int temp2 = ss[j];
ss[j] = ss[j+1];
ss[j + 1] = temp2;

for (int k = 0; k < ncrs; k++) {
int temp = s[j][k];
s[j][k] = s[j + 1][k];
s[j + 1][k] = temp;
}
}
}
}
}

void input_scores(int nstu, int ncrs, char (*name)[MAX_NAME_SIZE], int s[MAX_STU][MAX_COURSE+2],int ss[MAX_STU]){
for(int i=0;i<nstu;i++){
printf("학번 : ");
scanf("%d", &s[i][0]);
printf("이름 : ");
scanf("%s", name[i]);
}

for(int n=0;n<ncrs;n++){
for(int stu=0;stu<nstu;stu++){
printf("점수 : ");
scanf("%d",&s[stu][n+1]);
ss[stu] += s[stu][n+1];
}
}
}

void printf_scores(int nums,int ncrs, char (*name)[MAX_NAME_SIZE], int s[MAX_STU][MAX_COURSE+2],int ss[MAX_STU]){
int sum[MAX_STU]={0};
printf("이름\t학번\t");
for(int crs=1;crs<=ncrs;crs++){
printf("과목%d\t",crs);
if (crs == ncrs) {
printf("총합");
}
}
printf("\n");
for(int stu=0;stu<nums;stu++){
printf("%s\t", name[stu]);
for(int crs=0;crs<=ncrs;crs++){
printf("%d\t",s[stu][crs]);
}

printf("%d", ss[stu]);
printf("\n");
}
}

int main()
{
int score[MAX_STU][MAX_COURSE+2];
int numStu; //학생수
int numCourse;//과목수
int score_sum[MAX_STU] = { 0 };
char names[MAX_STU][MAX_NAME_SIZE];

if(scanf("%d%d",&numStu,&numCourse) !=2){
printf("입력오류\n");
return 1;
}

//크기 check
input_scores(numStu, numCourse, names, score, score_sum);
temp_score(numStu,numCourse, score,score_sum);
printf_scores(numStu,numCourse, names, score,score_sum);
}


전체 소스 코드

이상입니다.
["2차원 배열 포인터란?\n\nC언어를 처음 배우는 사람들에게 가장 어려운 부분이 포인터입니다. \n단일 변수의 포인터는 큰 어려움이 없습니다. \n배열 포인터나 함수 포인터 등을 접하기 시작하면 굉장히 복잡하고 헷갈립니다.\n\n특히, 배열 포인터와 포인터 배열은 혼동하기 쉽습니다.\n\n1. 2차원 배열 선언\n\n2차원 배열 포인터에 대해서 설명하기에 앞서서, 2차원 배열을 먼저 살펴봅시다.\n\nint a[2][3] = { 100, 101, 102, 103, 104, 105 };\n\n위의 코드를 통해서 우리는 2차원 배열을 선언하고, 사용할 수 있습니다.\n\n\n \n \n  \n Col #0\n Col #1\n Col #2\n \n \n \n \n Row #0\n 100\n 101\n 102\n \n \n Row #1\n 103\n 104\n 105\n \n \n\n\n2차원 배열을 액세스 하는 것은 아주 쉽습니다.\n\n2. 2차원 배열 포인터 선언\n\n2차원 배열을 가리키는 포인터는 어떻게 선언해야 할까요?\n\nvoid main(void)\n{\n int arr[2][3] = { 100, 101, 102, 103, 104, 105 };\n\n int (*p)[3] = arr;\n\n printf(\"%d\", p[1][2]);\n}\n\n\n소스 코드\n\nint arr[2][3];을 int (*p)[3];과 같은 형식으로 변환해주면 됩니다.\n\n프로그래밍 언어를 배우는 많은 사람들이 \n문법을 왜 그렇게 만들었는지 그 이유에 대해서 궁금해하곤 합니다.\n\n우리가 영어를 배우면서 영어 문법을 배울때, 문법을 왜 그렇게 만들었는지에 대해서 \n묻고 따지지 않는 것처럼 프로그래밍 언어 역시도 문법을 그렇게 정해놨기 때문에 \n“문법을 왜 이렇게 만들어 놨지?”라고 의문을 가지는 것은 큰 의미가 없습니다.\n\n그저 정해진 문법을 익히고 그에 맞게 구현해야 합니다.\n\n3. 2차원 배열 포인터를 함수 포인터로 넘기는 방법\n\n하지만 위의 배열의 포인터를 함수 인자로 넘겨야 한다면 어떻게 해야 할까요?\n\nvoid dump_data( int iRows, int iCols, int (*arr)[3] )\n{\n int i = 0;\n int j = 0;\n\n for ( i = 0 ; i < iRows ; i++ )\n {\n for ( j = 0 ; j < iCols ; j++ )\n {\n printf(\"%d \", arr[i][j]);\n }\n printf(\"", "\");\n } \n}\n\nvoid main(void)\n{\n int arr[2][3] = { 100, 101, 102, 103, 104, 105 };\n\n dump_data( 2, 3, arr);\n}\n\n\n소스 코드\n\n위와 같이 작성하고 빌드해서 실행하면 아래와 같은 결과가 나옵니다.\n\n100 101 102 \n103 104 105\n\n\n2차원 배열 포인터를 활용한 간단한 예제\n\n#include <stdio.h>\n#define MAX_STU 100\n#define MAX_COURSE 10\n#define MAX_NAME_SIZE 10\n\nvoid temp_score(int nstu, int ncrs, int s[MAX_STU][MAX_COURSE+2],int ss[MAX_STU]){\n for (int i = 0; i < nstu; i++) {\n for (int j = 0; j < (nstu - 1) - i; j++) {\n if (ss[j] < ss[j + 1]) { \n\n int temp2 = ss[j];\n ss[j] = ss[j+1];\n ss[j + 1] = temp2;\n\n for (int k = 0; k < ncrs; k++) {\n int temp = s[j][k];\n s[j][k] = s[j + 1][k];\n s[j + 1][k] = temp;\n }\n }\n }\n }\n}\n\nvoid input_scores(int nstu, int ncrs, char (*name)[MAX_NAME_SIZE], int s[MAX_STU][MAX_COURSE+2],int ss[MAX_STU]){\n for(int i=0;i<nstu;i++){\n\t printf(\"학번 : \");\n scanf(\"%d\", &s[i][0]);\n printf(\"이름 : \");\n scanf(\"%s\", name[i]);\n }\n \n for(int n=0;n<ncrs;n++){\n for(int stu=0;stu<nstu;stu++){\n printf(\"점수 : \");\n scanf(\"%d\",&s[stu][n+1]);\n ss[stu] += s[stu][n+1];\n }\n }\n}\n\nvoid printf_scores(int nums,int ncrs, char (*name)[MAX_NAME_SIZE], int s[MAX_STU][MAX_COURSE+2],int ss[MAX_STU]){\n int sum[MAX_STU]={0};\n printf(\"이름\\t학번\\t\");\n for(int crs=1;crs<=ncrs;crs++){\n printf(\"과목%d\\t\",crs);\n if (crs == ncrs) {\n printf(\"총합\");\n }\n }\n printf(\"", "\");\n for(int stu=0;stu<nums;stu++){\n printf(\"%s\\t\", name[stu]);\n \tfor(int crs=0;crs<=ncrs;crs++){ \n printf(\"%d\\t\",s[stu][crs]);\n \t}\n\n \tprintf(\"%d\", ss[stu]); \n \tprintf(\"", "\");\n }\n}\n\nint main()\n{\n int score[MAX_STU][MAX_COURSE+2];\n int numStu; //학생수\n int numCourse;//과목수 \n int score_sum[MAX_STU] = { 0 };\n char names[MAX_STU][MAX_NAME_SIZE];\n \n if(scanf(\"%d%d\",&numStu,&numCourse) !=2){\n printf(\"입력오류", "\");\n return 1;\n }\n\n //크기 check\n input_scores(numStu, numCourse, names, score, score_sum);\n temp_score(numStu,numCourse, score,score_sum);\n printf_scores(numStu,numCourse, names, score,score_sum);\n}\n\n\n전체 소스 코드\n\n이상입니다.\n"]
Title : 파일의 마지막 수정 시간을 가져오는 방법(Ubuntu Bash)
URL : /005_bash/001.html
Description : Ubuntu Bash Shell에서 파일의 마지막 수정 시간을 가져오는 방법에 대해서 설명합니다.
Content : 최종 수정 시간을 가져오는 간단한 방법 (Good)

파일의 마지막 수정 시간을 가져오는 아주 기초적인 방법은
$ date -r test.php와 같은 명령을 실행시키는 방법입니다.

명령어
$ date -r test.php


-r 옵션으로 파일의 마지막 수정 시간을 손쉽게 가져올 수 있습니다.

출력 결과
2022. 03. 08. (화) 18:13:20 KST


이런 방식의 출력 방법은 아주 간단하면서 사람이 식별하기는 편리하지만,
그 결과를 파싱해서 처리하는 경우에는 적합하지 못하다.
특히, 요일이 한글로 되어 있어서 다른 언어에서의 처리는 거의 불가능에 가깝다고 생각하면 된다.

특정 날짜 형식으로 최종 수정 시간을 가져오는 방법 (Better)

이번에는 좀 더 정형화된 방식으로 마지막 수정 시간을 가져오는 방법이다.

명령어
$ date +"%m-%d-%Y %H:%M:%S" -r test.php


출력 결과
03-08-2022 18:13:20


사람이 보기에도 편리하고 그 결과를 파싱하기도 아주 편리한 형식이다.
하지만 이 역시 치명적인 단점이 있다.
어떤 시각대의 시간 값인지 알 수 없다.
이 시간 값이 서울의 시간인지 독일의 시간인지 알 방법이 없다.

Time Zone 정보가 포함된 최종 수정 시간 표시 (Best)

이번에는 출력 결과에 시차를 추가하는 방법이다.

명령어
date +"%m-%d-%YT%H:%M:%S%:z" -r test.php


출력 결과

03-08-2022T18:13:20+09:00


출력 결과를 살펴보면 UTC(협정세계시)를 기준으로 9시가 더해져서 표시되는 것을 확인할 수 있다.
사람이 보기에도 편리하고, 그 결과를 파싱하기에도 편리하며, UTC 기준 시차까지 표기되어 있어서 거의 완벽하다.

(응용) 사이트맵을 명시하는 sitemap.xml 표시 형식

사실 이런 글을 작성할 때는 ‘왜?’라는 의문사부터 시작하는 것이 좋지만
최대한 빨리 원하는 내용을 찾아갈 수 있도록 “왜 이런 형식의 최종 수정 시간을 출력하는가?”에 대해서는 본 페이지의 마지막에 설명한다.

필자의 경우 이번에 새로 개설한 GitHub Pages의 사이트맵을 자동으로 생성하는 bash 스크립트를 작성하였다.
해당 스크립트의 결과로 생성되는 sitemap.xml 파일에 </code> 형식으로 해당 페이지의 마지막 수정 시간을 명시할 수 있다.

<url>
<loc>https://boyinblue.github.io/002_github_blog/001_advantage_of_github_blog.html</loc>
<lastmod>03-06-2022T23:25:06+09:00</lastmod>
<changefreq>weekly</changefreq>
</url>


이 때 사용되는 최종 수정 시간 포맷으로 사용하기 위함이다.
구글 검색 엔진과 같은 크롤링 로봇이 사이트 맵을 파싱하면서,
마지막으로 크롤링을 수행했던 시간과 해당 파일의 마지막 수정 시간을 비교한다.
그 결과 마지막 수정 시간 이후에 크롤링 이력이 있으면 해당 페이지는 크롤링하지 않을 것이고,
반대로 마지막 크롤링 시간 이후에 해당 파일이 수정되었다면 해당 페이지를 다시 크롤링 할 가능성이 크다.
["최종 수정 시간을 가져오는 간단한 방법 (Good)\n\n파일의 마지막 수정 시간을 가져오는 아주 기초적인 방법은 \n$ date -r test.php와 같은 명령을 실행시키는 방법입니다.\n\n명령어\n$ date -r test.php\n\n\n-r 옵션으로 파일의 마지막 수정 시간을 손쉽게 가져올 수 있습니다.\n\n출력 결과\n2022. 03. 08. (화) 18:13:20 KST\n\n\n이런 방식의 출력 방법은 아주 간단하면서 사람이 식별하기는 편리하지만, \n그 결과를 파싱해서 처리하는 경우에는 적합하지 못하다. \n특히, 요일이 한글로 되어 있어서 다른 언어에서의 처리는 거의 불가능에 가깝다고 생각하면 된다.\n\n특정 날짜 형식으로 최종 수정 시간을 가져오는 방법 (Better)\n\n이번에는 좀 더 정형화된 방식으로 마지막 수정 시간을 가져오는 방법이다.\n\n명령어\n$ date +\"%m-%d-%Y %H:%M:%S\" -r test.php\n\n\n출력 결과\n03-08-2022 18:13:20\n\n\n사람이 보기에도 편리하고 그 결과를 파싱하기도 아주 편리한 형식이다. \n하지만 이 역시 치명적인 단점이 있다. \n어떤 시각대의 시간 값인지 알 수 없다. \n이 시간 값이 서울의 시간인지 독일의 시간인지 알 방법이 없다.\n\nTime Zone 정보가 포함된 최종 수정 시간 표시 (Best)\n\n이번에는 출력 결과에 시차를 추가하는 방법이다.\n\n명령어\ndate +\"%m-%d-%YT%H:%M:%S%:z\" -r test.php\n\n\n출력 결과\n\n03-08-2022T18:13:20+09:00\n\n\n출력 결과를 살펴보면 UTC(협정세계시)를 기준으로 9시가 더해져서 표시되는 것을 확인할 수 있다. \n사람이 보기에도 편리하고, 그 결과를 파싱하기에도 편리하며, UTC 기준 시차까지 표기되어 있어서 거의 완벽하다.\n\n(응용) 사이트맵을 명시하는 sitemap.xml 표시 형식\n\n사실 이런 글을 작성할 때는 ‘왜?’라는 의문사부터 시작하는 것이 좋지만 \n최대한 빨리 원하는 내용을 찾아갈 수 있도록 “왜 이런 형식의 최종 수정 시간을 출력하는가?”에 대해서는 본 페이지의 마지막에 설명한다.\n\n필자의 경우 이번에 새로 개설한 GitHub Pages의 사이트맵을 자동으로 생성하는 bash 스크립트를 작성하였다. \n해당 스크립트의 결과로 생성되는 sitemap.xml 파일에 </code> 형식으로 해당 페이지의 마지막 수정 시간을 명시할 수 있다.\n\n<url>\n<loc>https://boyinblue.github.io/002_github_blog/001_advantage_of_github_blog.html</loc>\n<lastmod>03-06-2022T23:25:06+09:00</lastmod>\n<changefreq>weekly</changefreq>\n</url>\n\n\n이 때 사용되는 최종 수정 시간 포맷으로 사용하기 위함이다. \n구글 검색 엔진과 같은 크롤링 로봇이 사이트 맵을 파싱하면서, \n마지막으로 크롤링을 수행했던 시간과 해당 파일의 마지막 수정 시간을 비교한다. \n그 결과 마지막 수정 시간 이후에 크롤링 이력이 있으면 해당 페이지는 크롤링하지 않을 것이고, \n반대로 마지막 크롤링 시간 이후에 해당 파일이 수정되었다면 해당 페이지를 다시 크롤링 할 가능성이 크다.\n"]
Title : 파이썬 스크립트 실행시 No module named speech_recognition 에러가 발생했을 때 조치 방법
URL : /004_python/006-python-no-module-speech-recognition.html
Description : 파이썬 스크립트 실행시 No module named speech_recognition 이라는 에러가 발생했을 때 설치해야 하는 패키지명에 대해서 설명합니다.
Content : 문제의 상황

파이썬을 이용해서 TTS 기능을 하는 스크립트를 작성했습니다.
다른 PC에서 해당 스크립트를 실행해보니 아래와 같은 에러가 발생했습니다.

$ python3 tts.py
Traceback (most recent call last):
File "/project/tts/tts.py", line 1, in <module>
import speech_recognition as sr
ModuleNotFoundError: No module named 'speech_recognition'


위의 문제는 speech_recognition이라는 모듈을 찾지 못해서
발생한 문제입니다.

해결 방법

해결 방법은 아주 간단합니다.
SpeechRecognition이라는 패키지를 설치해주면 됩니다.

$ sudo pip3 install SpeechRecognition


모듈명이 speech_recognition라서
sudo pip3 install speech_recognition 명령으로
패키지를 설치하면 될 것 같지만 그렇지 않습니다.

패키지 설치를 위한 스크립트 작성

모듈명과 설치해야 할 패키지 명이 상이하기 때문에
파이썬 스크립트 배포시에 아래와 같이 패키지 설치를 위한
스크립트를 같이 발행하는 것이 좋습니다.

#!/bin/bash

sudo pip3 install SpeechRecognition


위와 같이 필요한 패키지를 설치할 수 있는 쉘 스크립트까지 같이 넣어준다면
해당 파이썬 스크립트를 실행할 때 훨씬 더 편리하겠습니다.

결론

파이썬 스크립트 실행시에
No module named 'spech_recognition'이라는 에러가 발생했다면
SpeechRecognition이라는 패키지를 설치해주면 해결됩니다.

이상입니다.
["문제의 상황\n\n파이썬을 이용해서 TTS 기능을 하는 스크립트를 작성했습니다. \n다른 PC에서 해당 스크립트를 실행해보니 아래와 같은 에러가 발생했습니다.\n\n$ python3 tts.py \nTraceback (most recent call last):\n File \"/project/tts/tts.py\", line 1, in <module>\n import speech_recognition as sr\nModuleNotFoundError: No module named 'speech_recognition'\n\n\n위의 문제는 speech_recognition이라는 모듈을 찾지 못해서 \n발생한 문제입니다.\n\n해결 방법\n\n해결 방법은 아주 간단합니다. \nSpeechRecognition이라는 패키지를 설치해주면 됩니다.\n\n$ sudo pip3 install SpeechRecognition\n\n\n모듈명이 speech_recognition라서 \nsudo pip3 install speech_recognition 명령으로 \n패키지를 설치하면 될 것 같지만 그렇지 않습니다.\n\n패키지 설치를 위한 스크립트 작성\n\n모듈명과 설치해야 할 패키지 명이 상이하기 때문에 \n파이썬 스크립트 배포시에 아래와 같이 패키지 설치를 위한 \n스크립트를 같이 발행하는 것이 좋습니다.\n\n#!/bin/bash\n\nsudo pip3 install SpeechRecognition\n\n\n위와 같이 필요한 패키지를 설치할 수 있는 쉘 스크립트까지 같이 넣어준다면 \n해당 파이썬 스크립트를 실행할 때 훨씬 더 편리하겠습니다.\n\n결론\n\n파이썬 스크립트 실행시에 \nNo module named 'spech_recognition'이라는 에러가 발생했다면\nSpeechRecognition이라는 패키지를 설치해주면 해결됩니다.\n\n이상입니다.\n"]
Title : USB-to-Serial 장치를 연결했지만 /dev/tty/ttyUSB0 파일이 생성되지 않는 경우 조치 방법
URL : /008_ubuntu/008-usb-to-serial-no-ttyUSB0.html
Description : Ubuntu Linux 22.04에 USB-to-Serial 장치를 연결했지만 ttyUSB0 파일이 생성되지 않는 경우 조치 방법 설명
Content : 리눅스 PC에 USB-to-Serial 케이블을 연결하면 자동으로
/dev/ttyUSB0와 같은 장치 파일일 생성되어야 합니다.

만약, 여러개의 USB-to-Serial 케이블을 연결했다면,
/dev/ttyUSB0, /dev/ttyUSB1 등
여러개의 장치 파일이 생성되어야 합니다.

하지만 최근 Ubuntu Linux 22.04로 업그레이드한 이후부터는
USB-to-Serial 케이블을 연결해도 /dev/ttyUSB0와 같은 파일들이
제대로 생성되지 못하는 문제가 목격되고 있습니다.

정확히 이야기하자면, /dev/ttyUSB0 파일이 생성되었다가,
금새 사라진다는 것이 좀 더 정확한 표현입니다.

이 문제를 정의하고 해결하는 방법에 대해서 설명을 드리고자 합니다.

문제의 현상

문제를 정확히 정의하고 원인을 찾아야 정확한 해결이 가능합니다.

lsusb명령을 통해서 인식된 USB 장치들을 확인합니다.

$ lsusb
Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 007: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
Bus 001 Device 008: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
Bus 001 Device 003: ID 03f0:1b4a HP, Inc HP Wireless Slim Keyboard - Skylab KR
Bus 001 Device 006: ID 03f0:f92a HP, Inc HP Color LaserJet MFP E785
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub


아래와 같이 USB-to-Serial 장치가 정상적으로 인식된 것을 확인할 수 있습니다.

Bus 001 Device 007: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
Bus 001 Device 008: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC


$ sudo udevadm monitor -u 명령으로 인식 로그를 살펴봅니다.

sudo udevadm monitor -u
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing

UDEV [82546.546942] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4 (usb)
UDEV [82546.563176] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0 (usb)
UDEV [82546.585015] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpiochip2 (gpio)
UDEV [82546.585142] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpio/gpiochip500 (gpio)
UDEV [82546.591547] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)
UDEV [82546.593562] bind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpiochip2 (gpio)
UDEV [82546.645324] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0/tty/ttyUSB0 (tty)
UDEV [82546.664143] bind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)
UDEV [82546.671965] bind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0 (usb)
UDEV [82546.692266] bind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4 (usb)
UDEV [82549.950939] remove /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpio/gpiochip500 (gpio)
UDEV [82549.951788] remove /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0/tty/ttyUSB0 (tty)
UDEV [82549.953358] unbind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpiochip2 (gpio)
UDEV [82549.959662] unbind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)
UDEV [82549.960285] remove /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpiochip2 (gpio)
UDEV [82549.965710] remove /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)
UDEV [82549.974262] unbind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0 (usb)


로그를 잘 살펴보면 ttyUSB0로 add되고 bind된 이후에,
unbind되고 remove 된 것을 알 수 있습니다.

UDEV [82546.645324] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0/tty/ttyUSB0 (tty)


UDEV [82546.664143] bind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)


UDEV [82549.959662] unbind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)


UDEV [82549.965710] remove /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)


해결 방법

/usr/lib/udev/rules.d/85-brltty.rules 파일을 열어서
USB-to-Serial로 인식된 코드를 주석 처리 합니다.

기존 설정

$ sudo vi /usr/lib/udev/rules.d/85-brltty.rules
# Device: 0403:6001
# Generic Identifier
# Vendor: Future Technology Devices International, Ltd
# Product: FT232 USB-Serial (UART) IC
# Albatross [all models]
# Cebra [all models]
# HIMS [Sync Braille]
# HandyTech [FTDI chip]
# Hedo [MobilLine]
# MDV [all models]
ENV{PRODUCT}=="403/6001/*", ATTRS{manufacturer}=="FTDI", ENV{BRLTTY_BRAILLE_DRIVER}="hd,hm,ht", GOTO="brltty_usb_run"
ENV{PRODUCT}=="403/6001/*", ATTRS{manufacturer}=="Hedo Reha Technik GmbH", ENV{BRLTTY_BRAILLE_DRIVER}="hd,hm,ht", GOTO="brltty_usb_run"


아래 라인들을 주석 처리합니다.

ENV{PRODUCT}=="403/6001/*", ATTRS{manufacturer}=="FTDI", ENV{BRLTTY_BRAILLE_DRIVER}="hd,hm,ht", GOTO="brltty_usb_run"
ENV{PRODUCT}=="403/6001/*", ATTRS{manufacturer}=="Hedo Reha Technik GmbH", ENV{BRLTTY_BRAILLE_DRIVER}="hd,hm,ht", GOTO="brltty_usb_run"


새 설정

$ sudo vi /usr/lib/udev/rules.d/85-brltty.rules
# Device: 0403:6001
# Generic Identifier
# Vendor: Future Technology Devices International, Ltd
# Product: FT232 USB-Serial (UART) IC
# Albatross [all models]
# Cebra [all models]
# HIMS [Sync Braille]
# HandyTech [FTDI chip]
# Hedo [MobilLine]
# MDV [all models]
#ENV{PRODUCT}=="403/6001/*", ATTRS{manufacturer}=="FTDI", ENV{BRLTTY_BRAILLE_DRIVER}="hd,hm,ht", GOTO="brltty_usb_run"
#ENV{PRODUCT}=="403/6001/*", ATTRS{manufacturer}=="Hedo Reha Technik GmbH", ENV{BRLTTY_BRAILLE_DRIVER}="hd,hm,ht", GOTO="brltty_usb_run"


시스템을 재부팅합니다.

$ sudo reboot


재부팅후에 USB-to-Serial 케이블이 제대로 인식되었는지 살펴봅니다.

$ ls /dev/ttyUSB*
/dev/ttyUSB0 /dev/ttyUSB1


정상적으로 인식된 것을 확인할 수 있었습니다.

환경

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 22.04 LTS
Release: 22.04
Codename: jammy


결론

Ubuntu Linux 22.04에서 USB-to-Serial 장치를 연결했음에도 불구하고
ttyUSB0와 같은 파일이 생성되지 않을 때는
/usr/lib/udev/rules.d/85-brltty.rules 파일에서
해당 부분을 주석 처리하고 재부팅하면 깔끔하게 해결이 됩니다.
["리눅스 PC에 USB-to-Serial 케이블을 연결하면 자동으로 \n/dev/ttyUSB0와 같은 장치 파일일 생성되어야 합니다.\n\n만약, 여러개의 USB-to-Serial 케이블을 연결했다면, \n/dev/ttyUSB0, /dev/ttyUSB1 등 \n여러개의 장치 파일이 생성되어야 합니다.\n\n하지만 최근 Ubuntu Linux 22.04로 업그레이드한 이후부터는 \nUSB-to-Serial 케이블을 연결해도 /dev/ttyUSB0와 같은 파일들이 \n제대로 생성되지 못하는 문제가 목격되고 있습니다.\n\n정확히 이야기하자면, /dev/ttyUSB0 파일이 생성되었다가, \n금새 사라진다는 것이 좀 더 정확한 표현입니다.\n\n이 문제를 정의하고 해결하는 방법에 대해서 설명을 드리고자 합니다.\n\n문제의 현상\n\n문제를 정확히 정의하고 원인을 찾아야 정확한 해결이 가능합니다.\n\nlsusb명령을 통해서 인식된 USB 장치들을 확인합니다.\n\n$ lsusb\nBus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub\nBus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub\nBus 001 Device 007: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC\nBus 001 Device 008: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC\nBus 001 Device 003: ID 03f0:1b4a HP, Inc HP Wireless Slim Keyboard - Skylab KR\nBus 001 Device 006: ID 03f0:f92a HP, Inc HP Color LaserJet MFP E785\nBus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub\nBus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub\n\n\n아래와 같이 USB-to-Serial 장치가 정상적으로 인식된 것을 확인할 수 있습니다.\n\nBus 001 Device 007: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC\nBus 001 Device 008: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC\n\n\n$ sudo udevadm monitor -u 명령으로 인식 로그를 살펴봅니다.\n\nsudo udevadm monitor -u\nmonitor will print the received events for:\nUDEV - the event which udev sends out after rule processing\n\nUDEV [82546.546942] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4 (usb)\nUDEV [82546.563176] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0 (usb)\nUDEV [82546.585015] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpiochip2 (gpio)\nUDEV [82546.585142] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpio/gpiochip500 (gpio)\nUDEV [82546.591547] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)\nUDEV [82546.593562] bind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpiochip2 (gpio)\nUDEV [82546.645324] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0/tty/ttyUSB0 (tty)\nUDEV [82546.664143] bind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)\nUDEV [82546.671965] bind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0 (usb)\nUDEV [82546.692266] bind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4 (usb)\nUDEV [82549.950939] remove /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpio/gpiochip500 (gpio)\nUDEV [82549.951788] remove /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0/tty/ttyUSB0 (tty)\nUDEV [82549.953358] unbind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpiochip2 (gpio)\nUDEV [82549.959662] unbind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)\nUDEV [82549.960285] remove /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/gpiochip2 (gpio)\nUDEV [82549.965710] remove /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)\nUDEV [82549.974262] unbind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0 (usb)\n\n\n로그를 잘 살펴보면 ttyUSB0로 add되고 bind된 이후에, \nunbind되고 remove 된 것을 알 수 있습니다.\n\nUDEV [82546.645324] add /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0/tty/ttyUSB0 (tty)\n\n\nUDEV [82546.664143] bind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)\n\n\nUDEV [82549.959662] unbind /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)\n\n\nUDEV [82549.965710] remove /devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0 (usb-serial)\n\n\n해결 방법\n\n/usr/lib/udev/rules.d/85-brltty.rules 파일을 열어서 \nUSB-to-Serial로 인식된 코드를 주석 처리 합니다.\n\n기존 설정\n\n$ sudo vi /usr/lib/udev/rules.d/85-brltty.rules\n# Device: 0403:6001\n# Generic Identifier\n# Vendor: Future Technology Devices International, Ltd\n# Product: FT232 USB-Serial (UART) IC\n# Albatross [all models]\n# Cebra [all models]\n# HIMS [Sync Braille]\n# HandyTech [FTDI chip]\n# Hedo [MobilLine]\n# MDV [all models]\nENV{PRODUCT}==\"403/6001/*\", ATTRS{manufacturer}==\"FTDI\", ENV{BRLTTY_BRAILLE_DRIVER}=\"hd,hm,ht\", GOTO=\"brltty_usb_run\"\nENV{PRODUCT}==\"403/6001/*\", ATTRS{manufacturer}==\"Hedo Reha Technik GmbH\", ENV{BRLTTY_BRAILLE_DRIVER}=\"hd,hm,ht\", GOTO=\"brltty_usb_run\"\n\n\n아래 라인들을 주석 처리합니다.\n\nENV{PRODUCT}==\"403/6001/*\", ATTRS{manufacturer}==\"FTDI\", ENV{BRLTTY_BRAILLE_DRIVER}=\"hd,hm,ht\", GOTO=\"brltty_usb_run\"\nENV{PRODUCT}==\"403/6001/*\", ATTRS{manufacturer}==\"Hedo Reha Technik GmbH\", ENV{BRLTTY_BRAILLE_DRIVER}=\"hd,hm,ht\", GOTO=\"brltty_usb_run\"\n\n\n새 설정\n\n$ sudo vi /usr/lib/udev/rules.d/85-brltty.rules\n# Device: 0403:6001\n# Generic Identifier\n# Vendor: Future Technology Devices International, Ltd\n# Product: FT232 USB-Serial (UART) IC\n# Albatross [all models]\n# Cebra [all models]\n# HIMS [Sync Braille]\n# HandyTech [FTDI chip]\n# Hedo [MobilLine]\n# MDV [all models]\n#ENV{PRODUCT}==\"403/6001/*\", ATTRS{manufacturer}==\"FTDI\", ENV{BRLTTY_BRAILLE_DRIVER}=\"hd,hm,ht\", GOTO=\"brltty_usb_run\"\n#ENV{PRODUCT}==\"403/6001/*\", ATTRS{manufacturer}==\"Hedo Reha Technik GmbH\", ENV{BRLTTY_BRAILLE_DRIVER}=\"hd,hm,ht\", GOTO=\"brltty_usb_run\"\n\n\n시스템을 재부팅합니다.\n\n$ sudo reboot\n\n\n재부팅후에 USB-to-Serial 케이블이 제대로 인식되었는지 살펴봅니다.\n\n$ ls /dev/ttyUSB*\n/dev/ttyUSB0 /dev/ttyUSB1\n\n\n정상적으로 인식된 것을 확인할 수 있었습니다.\n\n환경\n\n$ lsb_release -a\nNo LSB modules are available.\nDistributor ID:\tUbuntu\nDescription:\tUbuntu 22.04 LTS\nRelease:\t22.04\nCodename:\tjammy\n\n\n결론\n\nUbuntu Linux 22.04에서 USB-to-Serial 장치를 연결했음에도 불구하고 \nttyUSB0와 같은 파일이 생성되지 않을 때는 \n/usr/lib/udev/rules.d/85-brltty.rules 파일에서 \n해당 부분을 주석 처리하고 재부팅하면 깔끔하게 해결이 됩니다.\n"]
Title : 파이썬 홈디렉토리 파일 오픈 방법
URL : /004_python/005-python-cannot-read-home-directory.html
Description : 파이썬에서 홈 디렉토리의 파일을 오픈하는 방법에 대해서 설명합니다.
Content : 파이썬의 플랫폼 독립성과 홈 디렉토리

파이썬에서 홈 디렉토리 파일을 오픈하는 방법에 설명하기에 앞서서
파이썬의 플랫폼 독립성에 대해서 잠깐 언급하고자 합니다.

파이썬의 플랫폼 독립성

파이썬이 프로그래밍 언어로써 널리 사랑을 받는 이유는
여러가지가 있겠습니다만,
그 중에서도 플랫폼에 dependent 하다는 것이 큰 장점이라고 생각합니다.

만약 우리가 C언어로 어떤 프로그램을 제작한다면,
윈도우즈용 프로그램과 리눅스용 프로그램을 2중으로 제작해야 합니다.

간단한 콘솔 프로그램일 경우는 소스 코드는 공통이겠지만,
윈도우즈에서도 컴파일을 해야 하고, 리눅스에서도 컴파일을 해야 합니다.

반면, 파이썬 스크립트는 플랫폼(OS)에 독립적이기 때문에
하나의 스크립트가 윈도우즈에서도 실행되고,
리눅스에서도 잘 실행됩니다.

필자가 Bash Shell Script를 몹시 아끼면서도
파이썬에 관심을 갖게 된 배경에도 플랫폼에 종속적이지 않은
파이썬의 특징 때문이었습니다.

물론 윈도우즈에서 Bash Shell Script를 실행시킬 수 있는
방법이 전혀 없는 것은 아니지만,
리눅스에서의 쉘 스크립트 실행과 호환성이 상당히 떨어져서
결국은 가급적이면 파이썬으로 스크립트를 작성하고 있습니다.

정말 플랫폼에 독립적인 것인가?

우리가 파이썬 패키지를 import 시켜서 사용할 때,
윈도우즈와 리눅스를 가리지 않고 import 시켜서 사용하기 때문에
파이썬이 플랫폼에 독립적인 것처럼 보일 수도 있겠습니다만,
겉보기와는 달리 실상은 그렇지 않습니다.

아래는 mp3 파일을 재생할 수 있는 playsound라는 패키지의
스크립트 일부를 발췌한 것입니다.

출처 : https://github.com/TaylorSMarks/playsound

from platform import system
system = system()

if system == 'Windows':
playsound = _playsoundWin
elif system == 'Darwin':
playsound = _playsoundOSX
# 중략
else:
playsound = _playsoundNix
# 중략


외부에서는 playsound라는 함수를 플랫폼과 무관하게 사용하지만,
내부는 OS에 따라서 구현이 다르다는 것을 알 수 있습니다.

리눅스의 홈 디렉토리 파일을 열 수 있는가?

그렇다면, 리눅스에서 널리 사용되는 홈 디렉토리에 있는 파일을
파이썬에서 엑세스 할 수 있는가에 대해서 살펴보겠습니다.

def openFile(filename):
fp = open("~/{}".format(filename))
line = fp.readline()
print(line)

openFile(".git-credentials")


위의 파이썬 스크립트는 홈 디렉토리의 .git-credential 파일을
열어서 한 줄을 출력합니다.

아주 간단한 스크립트이지만 실행해보면 아래와 같이
FileNotFoundError 에러가 발생합니다.

$ python3 home_directory.py
Traceback (most recent call last):
File "home_directory.py", line 19, in <module>
openFile(".git-credential")
File "home_directory.py", line 4, in openFile
fp = open("~/{}".format(filename))
FileNotFoundError: [Errno 2] No such file or directory: '~/.git-credentialis'


리눅스에서 홈 디렉토리를 의미하는 ~를
이해하지 못하기 때문입니다.

홈 디렉토리 파일을 여는 방법

아주 간단하게 홈 디렉토리 경로를 절대 경로로 넣어주면
파일을 정상적으로 엑세스 할 수 있습니다.

하지만 이런 내용을 언급하기 위해서
이 글을 작성하고 있는것은 아닙니다.

더군다나 사용자명에 따라서 절대 경로를 달라지기 때문에
이 방법은 좋은 방법도 아닙니다.

def openFileByFullPath(full_path):
fp = open(full_path)
line = fp.readline()
print(line)

openFileByFullPath("/home/boyinblue/.git-credential")


위와 같이 스크립트를 작성하고 실행을 하게 되면,
원하는 결과를 얻기는 했지만, 뭔가 만족스럽지 못합니다.

expanduser 함수 사용

리눅스 홈디렉토리의 경로를 가져올 수 있는
expanderuser() 함수를 사용하면 깔끔하게 해결됩니다.

def openFile2(filename):
home_dir = os.path.expanduser('~')
fp = open("{}/{}".format(home_dir, filename))
line = fp.readline()
print(line)

openFile2(".git-credentials")


homd_dir = os.path.expanduser('~') 구문에서
우리가 원하던 ~의 절대 경로를 가져올 수 있습니다.

구문에서 미루어 짐작할 수 있듯이, import os 구문이 필요합니다.

결론

리눅스의 홈 디렉토리인 ~ 경로 내부의 파일을
파이썬에서 엑세스 하시려면 os.path.expanduser('~') 구문을
사용하시면 되겠습니다.
["파이썬의 플랫폼 독립성과 홈 디렉토리\n\n파이썬에서 홈 디렉토리 파일을 오픈하는 방법에 설명하기에 앞서서 \n파이썬의 플랫폼 독립성에 대해서 잠깐 언급하고자 합니다.\n\n파이썬의 플랫폼 독립성\n\n파이썬이 프로그래밍 언어로써 널리 사랑을 받는 이유는 \n여러가지가 있겠습니다만, \n그 중에서도 플랫폼에 dependent 하다는 것이 큰 장점이라고 생각합니다.\n\n만약 우리가 C언어로 어떤 프로그램을 제작한다면, \n윈도우즈용 프로그램과 리눅스용 프로그램을 2중으로 제작해야 합니다.\n\n간단한 콘솔 프로그램일 경우는 소스 코드는 공통이겠지만, \n윈도우즈에서도 컴파일을 해야 하고, 리눅스에서도 컴파일을 해야 합니다.\n\n반면, 파이썬 스크립트는 플랫폼(OS)에 독립적이기 때문에 \n하나의 스크립트가 윈도우즈에서도 실행되고, \n리눅스에서도 잘 실행됩니다.\n\n필자가 Bash Shell Script를 몹시 아끼면서도 \n파이썬에 관심을 갖게 된 배경에도 플랫폼에 종속적이지 않은 \n파이썬의 특징 때문이었습니다.\n\n물론 윈도우즈에서 Bash Shell Script를 실행시킬 수 있는 \n방법이 전혀 없는 것은 아니지만, \n리눅스에서의 쉘 스크립트 실행과 호환성이 상당히 떨어져서 \n결국은 가급적이면 파이썬으로 스크립트를 작성하고 있습니다.\n\n정말 플랫폼에 독립적인 것인가?\n\n우리가 파이썬 패키지를 import 시켜서 사용할 때, \n윈도우즈와 리눅스를 가리지 않고 import 시켜서 사용하기 때문에 \n파이썬이 플랫폼에 독립적인 것처럼 보일 수도 있겠습니다만, \n겉보기와는 달리 실상은 그렇지 않습니다.\n\n아래는 mp3 파일을 재생할 수 있는 playsound라는 패키지의 \n스크립트 일부를 발췌한 것입니다.\n\n출처 : https://github.com/TaylorSMarks/playsound\n\nfrom platform import system\nsystem = system()\n\nif system == 'Windows':\n playsound = _playsoundWin\nelif system == 'Darwin':\n playsound = _playsoundOSX\n # 중략\nelse:\n playsound = _playsoundNix\n # 중략\n\n\n외부에서는 playsound라는 함수를 플랫폼과 무관하게 사용하지만, \n내부는 OS에 따라서 구현이 다르다는 것을 알 수 있습니다.\n\n리눅스의 홈 디렉토리 파일을 열 수 있는가?\n\n그렇다면, 리눅스에서 널리 사용되는 홈 디렉토리에 있는 파일을 \n파이썬에서 엑세스 할 수 있는가에 대해서 살펴보겠습니다.\n\ndef openFile(filename):\n fp = open(\"~/{}\".format(filename))\n line = fp.readline()\n print(line)\n\nopenFile(\".git-credentials\")\n\n\n위의 파이썬 스크립트는 홈 디렉토리의 .git-credential 파일을 \n열어서 한 줄을 출력합니다.\n\n아주 간단한 스크립트이지만 실행해보면 아래와 같이 \nFileNotFoundError 에러가 발생합니다.\n\n$ python3 home_directory.py \nTraceback (most recent call last):\n File \"home_directory.py\", line 19, in <module>\n openFile(\".git-credential\")\n File \"home_directory.py\", line 4, in openFile\n fp = open(\"~/{}\".format(filename))\nFileNotFoundError: [Errno 2] No such file or directory: '~/.git-credentialis'\n\n\n리눅스에서 홈 디렉토리를 의미하는 ~를 \n이해하지 못하기 때문입니다.\n\n홈 디렉토리 파일을 여는 방법\n\n아주 간단하게 홈 디렉토리 경로를 절대 경로로 넣어주면 \n파일을 정상적으로 엑세스 할 수 있습니다.\n\n하지만 이런 내용을 언급하기 위해서 \n이 글을 작성하고 있는것은 아닙니다.\n\n더군다나 사용자명에 따라서 절대 경로를 달라지기 때문에 \n이 방법은 좋은 방법도 아닙니다.\n\ndef openFileByFullPath(full_path):\n fp = open(full_path)\n line = fp.readline()\n print(line)\n\nopenFileByFullPath(\"/home/boyinblue/.git-credential\")\n\n\n위와 같이 스크립트를 작성하고 실행을 하게 되면, \n원하는 결과를 얻기는 했지만, 뭔가 만족스럽지 못합니다.\n\nexpanduser 함수 사용\n\n리눅스 홈디렉토리의 경로를 가져올 수 있는 \nexpanderuser() 함수를 사용하면 깔끔하게 해결됩니다.\n\ndef openFile2(filename):\n home_dir = os.path.expanduser('~')\n fp = open(\"{}/{}\".format(home_dir, filename))\n line = fp.readline()\n print(line)\n\nopenFile2(\".git-credentials\")\n\n\nhomd_dir = os.path.expanduser('~') 구문에서 \n우리가 원하던 ~의 절대 경로를 가져올 수 있습니다.\n\n구문에서 미루어 짐작할 수 있듯이, import os 구문이 필요합니다.\n\n결론\n\n리눅스의 홈 디렉토리인 ~ 경로 내부의 파일을 \n파이썬에서 엑세스 하시려면 os.path.expanduser('~') 구문을 \n사용하시면 되겠습니다.\n"]
Title : 마이크로 서보 9G 모터 핀 번호 (라즈베리파이4B 서보 모터 제어 방법)
URL : /010_raspberry/003-rpi4-servo-motor-control.html
Description : 마이크로 서보 9G 모터 핀 번호 및 라즈베리파이4B에서 서보 모터 제어 방법 설명
Content : 우리는 라즈베리파이와 아두이노를 교육용으로 널리 사용하고 있습니다.
교육용 키트에 주로 사용되는 마이크로 서보 9G 모터에 대해서 설명합니다.

마이크로 9G 서보 모터란?

모터의 종류는 상당히 다양합니다.
DC 모터, 스텝 모터, BLDC 모터, 서보 모터 등 다양한 모터들이 있습니다.

오늘은 서보 모터 중에서도 라즈베리파이나 아두이노에서
교육용으로 널리 사용중인 마이크로 9G 서보 모터에 대해서 설명드리겠습니다.

마이크로 9G 서보 모터는 회전 반영이 0도 ~ 180도의 모터입니다.
PWM 신호를 통해서 모터의 각도를 제어할 수 있습니다.

하지만 저가의 교육용 서보 모터라서 원하는 각도로 정밀하게 제어가 불가하고,
토크 또한 약해서 작은 부하에도 동작하지 못하는 단점이 있습니다.

서보 모터 핀번호






핀 번호
색 깔
설 명
비 고




1
주황색
PWM
모터 제어를 위한 PWM 신호


2
빨간색
VCC
5V


3
갈색
GND
 




위의 사진에 보이는 마이크로 서보 9G 모터는 5V로 동작합니다.
이 때문에 2번 핀과 3번 핀에 5V를 인가합니다.

1번 핀에 PWM을 이용하여 서보 모터의 각도를 제어할 수 있습니다.

PWM 제어 가능한 핀번호

VCC와 GND는 라즈베리파이의 어디에 연결해야 하는지
전혀 고민없이 연결하면 됩니다.

반면, PWM 신호의 경우는 어느 핀에 연결해야 하는지
살펴볼 필요가 있습니다.

그 이유는 Alt Function으로 PWM을 지원하는 핀을
선택해야 하기 때문입니다.

정답지부터 말씀드리자면 PWM 제어가 가능한 핀 번호는
GPIO 12, GPIO 13,
GPIO 18, GPIO 19 총 4개입니다.

자세한 핀맵은 아래 테이블을 참고하시기 바랍니다.




GPIO
Pull
ALT0
ALT1
ALT2
ALT3
ALT4
ALT5




0
High
SDA0
SA5
PCLK
SPI3 CE0 N
TXD2
SDA6


1
High
SCL0
SA4
DE
SPI3 MISO
RXD2
SCL6


2
High
SDA1
SA3
LCD VSYNC
SPI3 MOSI
CTS2
SDA3


3
High
SCL1
SA2
LCD HSYNC
SPI3 SCLK
RTS2
SCL3


4
High
GPCLK0
SA1
DPI D0
SPI4 CE0 N
TXD3
SDA3


5
High
GPCLK1
SA0
DPI D1
SPI4 MISO
RXD3
SCL3


6
High
GPCLK2
SOE N
DPI D2
SPI4 MOSI
CTS3
SDA4


7
High
SPI0 CE1 N
SWE N
DPI D3
SPI4 SCLK
RTS3
SCL4


8
High
SPI0 CE0 N
SD0
DPI D4
-
TXD4
SDA4


9
Low
SPI0 MISO
SD1
DPI D5
-
RXD4
SCL4


10
Low
SPI0 MOSI
SD2
DPI D6
-
CTS4
SDA5


11
Low
SPI0 SCLK
SD3
DPI D7
-
RTS4
SCL5


12
Low
PWM0
SD4
DPI D8
SPI5 CE0 N
TXD5
SDA5


13
Low
PWM1
SD5
DPI D9
SPI5 MISO
RXD5
SCL5


14
Low
TXD0
SD6
DPI D10
SPI5 MOSI
CTS5
TXD1


15
Low
RXD0
SD7
DPI D11
SPI5 SCLK
RTS5
RXD1


16
Low
FL0
SD8
DPI D12
CTS0
SPI1 CE2 N
CTS1


17
Low
FL1
SD9
DPI D13
RTS0
SPI1 CE1 N
RTS1


18
Low
PCM CLK
SD10
DPI D14
SPI6 CE0 N
SPI1 CE0 N
PWM0


19
Low
PCM FS
SD11
DPI D15
SPI6 MISO
SPI1 MISO
PWM1


20
Low
PCM DIN
SD12
DPI D16
SPI6 MOSI
SPI1 MOSI
GPCLK0


21
Low
PCM DOUT
SD13
DPI D17
SPI6 SCLK
SPI1 SCLK
GPCLK1


22
Low
SD0 CLK
SD14
DPI D18
SD1 CLK
ARM TRST
SDA6


23
Low
SD0 CMD
SD15
DPI D19
SD1 CMD
ARM RTCK
SCL6


24
Low
SD0 DAT0
SD16
DPI D20
SD1 DAT0
ARM TDO
SPI3 CE1 N


25
Low
SD0 DAT1
SD17
DPI D21
SD1 DAT1
ARM TCK
SPI4 CE1 N


26
Low
SD0 DAT2
TE0
DPI D22
SD1 DAT2
ARM TDI
SPI5 CE1 N


27
Low
SD0 DAT3
TE1
DPI D23
SD1 DAT3
ARM TMS
SPI6 CE1 N




서보 모터 제어 예제

아래는 파이썬을 이용한 서보 모터 제어 예제입니다.

#!/usr/bin/env python

import RPi.GPIO as GPIO
import time

pin_num = None

def serbo_init(serbo_pin_num = 18):
global pin_num

GPIO.setmode(GPIO.BCM)
pin_num = serbo_pin_num
GPIO.setup(pin_num, GPIO.OUT)

def set_degree(degree):
phz = GPIO.PWM(pin_num, 100)
phz.start(5)
duty = degree / 10.0 + 2.5
phz.ChangeDutyCycle(duty)
time.sleep(0.5)

def main():
while True:
degree = float( input("제어할 각도 :") )
set_degree(degree)

GPIO.cleanup()

if __name__ == '__main__':
serbo_init()
main()


결론

라즈베리파이 및 아두이노에서 교육용으로 널리 사용중인
마이크로 서보 9G 모터에 대한 간략한 설명 및
제어 예제에 대한 설명을 모두 마칩니다.
["우리는 라즈베리파이와 아두이노를 교육용으로 널리 사용하고 있습니다. \n교육용 키트에 주로 사용되는 마이크로 서보 9G 모터에 대해서 설명합니다.\n\n마이크로 9G 서보 모터란?\n\n모터의 종류는 상당히 다양합니다. \nDC 모터, 스텝 모터, BLDC 모터, 서보 모터 등 다양한 모터들이 있습니다.\n\n오늘은 서보 모터 중에서도 라즈베리파이나 아두이노에서 \n교육용으로 널리 사용중인 마이크로 9G 서보 모터에 대해서 설명드리겠습니다.\n\n마이크로 9G 서보 모터는 회전 반영이 0도 ~ 180도의 모터입니다. \nPWM 신호를 통해서 모터의 각도를 제어할 수 있습니다.\n\n하지만 저가의 교육용 서보 모터라서 원하는 각도로 정밀하게 제어가 불가하고, \n토크 또한 약해서 작은 부하에도 동작하지 못하는 단점이 있습니다.\n\n서보 모터 핀번호\n\n\n\n\n \n \n 핀 번호\n 색 깔\n 설 명\n 비 고\n \n \n \n \n 1\n 주황색\n PWM\n 모터 제어를 위한 PWM 신호\n \n \n 2\n 빨간색\n VCC\n 5V\n \n \n 3\n 갈색\n GND\n  \n \n \n\n\n위의 사진에 보이는 마이크로 서보 9G 모터는 5V로 동작합니다. \n이 때문에 2번 핀과 3번 핀에 5V를 인가합니다.\n\n1번 핀에 PWM을 이용하여 서보 모터의 각도를 제어할 수 있습니다.\n\nPWM 제어 가능한 핀번호\n\nVCC와 GND는 라즈베리파이의 어디에 연결해야 하는지 \n전혀 고민없이 연결하면 됩니다.\n\n반면, PWM 신호의 경우는 어느 핀에 연결해야 하는지 \n살펴볼 필요가 있습니다.\n\n그 이유는 Alt Function으로 PWM을 지원하는 핀을 \n선택해야 하기 때문입니다.\n\n정답지부터 말씀드리자면 PWM 제어가 가능한 핀 번호는 \nGPIO 12, GPIO 13, \nGPIO 18, GPIO 19 총 4개입니다.\n\n자세한 핀맵은 아래 테이블을 참고하시기 바랍니다.\n\n\n \n \n GPIO\n Pull\n ALT0\n ALT1\n ALT2\n ALT3\n ALT4\n ALT5\n \n \n \n \n 0\n High\n SDA0\n SA5\n PCLK\n SPI3 CE0 N\n TXD2\n SDA6\n \n \n 1\n High\n SCL0\n SA4\n DE\n SPI3 MISO\n RXD2\n SCL6\n \n \n 2\n High\n SDA1\n SA3\n LCD VSYNC\n SPI3 MOSI\n CTS2\n SDA3\n \n \n 3\n High\n SCL1\n SA2\n LCD HSYNC\n SPI3 SCLK\n RTS2\n SCL3\n \n \n 4\n High\n GPCLK0\n SA1\n DPI D0\n SPI4 CE0 N\n TXD3\n SDA3\n \n \n 5\n High\n GPCLK1\n SA0\n DPI D1\n SPI4 MISO\n RXD3\n SCL3\n \n \n 6\n High\n GPCLK2\n SOE N\n DPI D2\n SPI4 MOSI\n CTS3\n SDA4\n \n \n 7\n High\n SPI0 CE1 N\n SWE N\n DPI D3\n SPI4 SCLK\n RTS3\n SCL4\n \n \n 8\n High\n SPI0 CE0 N\n SD0\n DPI D4\n -\n TXD4\n SDA4\n \n \n 9\n Low\n SPI0 MISO\n SD1\n DPI D5\n -\n RXD4\n SCL4\n \n \n 10\n Low\n SPI0 MOSI\n SD2\n DPI D6\n -\n CTS4\n SDA5\n \n \n 11\n Low\n SPI0 SCLK\n SD3\n DPI D7\n -\n RTS4\n SCL5\n \n \n 12\n Low\n PWM0\n SD4\n DPI D8\n SPI5 CE0 N\n TXD5\n SDA5\n \n \n 13\n Low\n PWM1\n SD5\n DPI D9\n SPI5 MISO\n RXD5\n SCL5\n \n \n 14\n Low\n TXD0\n SD6\n DPI D10\n SPI5 MOSI\n CTS5\n TXD1\n \n \n 15\n Low\n RXD0\n SD7\n DPI D11\n SPI5 SCLK\n RTS5\n RXD1\n \n \n 16\n Low\n FL0\n SD8\n DPI D12\n CTS0\n SPI1 CE2 N\n CTS1\n \n \n 17\n Low\n FL1\n SD9\n DPI D13\n RTS0\n SPI1 CE1 N\n RTS1\n \n \n 18\n Low\n PCM CLK\n SD10\n DPI D14\n SPI6 CE0 N\n SPI1 CE0 N\n PWM0\n \n \n 19\n Low\n PCM FS\n SD11\n DPI D15\n SPI6 MISO\n SPI1 MISO\n PWM1\n \n \n 20\n Low\n PCM DIN\n SD12\n DPI D16\n SPI6 MOSI\n SPI1 MOSI\n GPCLK0\n \n \n 21\n Low\n PCM DOUT\n SD13\n DPI D17\n SPI6 SCLK\n SPI1 SCLK\n GPCLK1\n \n \n 22\n Low\n SD0 CLK\n SD14\n DPI D18\n SD1 CLK\n ARM TRST\n SDA6\n \n \n 23\n Low\n SD0 CMD\n SD15\n DPI D19\n SD1 CMD\n ARM RTCK\n SCL6\n \n \n 24\n Low\n SD0 DAT0\n SD16\n DPI D20\n SD1 DAT0\n ARM TDO\n SPI3 CE1 N\n \n \n 25\n Low\n SD0 DAT1\n SD17\n DPI D21\n SD1 DAT1\n ARM TCK\n SPI4 CE1 N\n \n \n 26\n Low\n SD0 DAT2\n TE0\n DPI D22\n SD1 DAT2\n ARM TDI\n SPI5 CE1 N\n \n \n 27\n Low\n SD0 DAT3\n TE1\n DPI D23\n SD1 DAT3\n ARM TMS\n SPI6 CE1 N\n \n \n\n\n서보 모터 제어 예제\n\n아래는 파이썬을 이용한 서보 모터 제어 예제입니다.\n\n#!/usr/bin/env python\n\nimport RPi.GPIO as GPIO\nimport time\n\npin_num = None\n\ndef serbo_init(serbo_pin_num = 18):\n global pin_num\n\n GPIO.setmode(GPIO.BCM)\n pin_num = serbo_pin_num\n GPIO.setup(pin_num, GPIO.OUT)\n\ndef set_degree(degree):\n phz = GPIO.PWM(pin_num, 100)\n phz.start(5)\n duty = degree / 10.0 + 2.5\n phz.ChangeDutyCycle(duty)\n time.sleep(0.5)\n\ndef main():\n while True:\n degree = float( input(\"제어할 각도 :\") )\n set_degree(degree)\n\n GPIO.cleanup()\n\nif __name__ == '__main__':\n serbo_init()\n main()\n\n\n결론\n\n라즈베리파이 및 아두이노에서 교육용으로 널리 사용중인 \n마이크로 서보 9G 모터에 대한 간략한 설명 및 \n제어 예제에 대한 설명을 모두 마칩니다.\n"]
Title : 구글 애드센스 ads.txt 문제 해결 방법
URL : /002_github_blog/014-google-adsense-ads-txt-warning.html
Description : 구글 애드센스에서 ads.txt 파일에 문제가 있을 경우 조치 방법
Content : GitHub Pages에서 ads.txt 파일 생성이 필요한 이유

무료 웹서버인 GitHub Pages로 웹서버를 운영한지도
1개월이 조금 더 지났습니다.
기존에 운영하던 네이버 블로그와 티스토리 블로그와는 달리
GitHub Pages는 참 매력적이 점이 많이 있습니다.

하루에 발행할 수 있는 페이지 수에 제한이 없고,
이로 인해서 파이썬이나 배쉬와 같은 스크립트를 이용해서
자동으로 컨텐츠를 생성해 낼 수도 있습니다.

또한, markdown 문법으로 시원시원하게 웹 페이지를 작성할 수 있습니다.

많은 강점들을 가지고 있지만, 동시에 여러 단점들도 존재합니다.

기존에 티스토리 블로그를 운영할 때에는 사이트맵 파일을 생성할 필요도 없고,
robots.txt 파일이나 ads.txt 같은 파일을
전혀 신경 쓸 필요가 없었습니다.

하지만 GitHub Pages에서는 블로그 주인이 이런 파일들을
모두 신경써서 챙겨줘야 하는 단점이 있습니다.

문제의 현상



GitHub Pages를 생성한지 약 십여일만에 구글 애드센스 연동이 가능했고,
티스토리에서 구글 애드센스를 연동했을 때는 경험하지 못한
생경한 경고 메시지를 만나게 되었습니다.

구글 애드센스 페이지에 접속하면 “수익 손실 위험 - 수익에 심각한 영향을 미치지 않도록 사이트에서 발견된 ads.txt 파일 문제를 해결해야 합니다.”라는 경고 메시지가 떴습니다.

문제의 원인

웹 페이지의 루트 디렉토리에 ads.txt 파일이 존재하지 않아서 발생한 문제입니다.

조치 방법

웹 페이지의 루트 디렉토리에 ads.txt 파일을 생성하고,
파일 안에 아래와 같은 형식으로 입력해주면 됩니다.

google.com, pub-XXXXXXXXXXXXXXXX, DIRECT, XXXXXXXXXXXXXXXX


참고로 ads.txt 파일에 포함되어야 할 내용은
구글 애드센스에서 친절하게 제공합니다.

문제 해결 확인

위와 같이 웹 페이지의 루트 디렉토리에 ads.txt 파일을
구글 애드센스에서 가이드한 포맷으로 작성해줬더니 문제가 해결되었습니다.

그리고 지금 아주 미미하지만 구글 애드센스 수익이 발생하기 시작했습니다.

결론

구글 애드센스에서 ads.txt 파일 관련 경고 메시지가 뜨면,
구글 애드센스에서 제공하는 ads.txt 파일을
웹 페이지의 루트 디렉토리에 업로드해주면 깔끔하게 해결됩니다.

["GitHub Pages에서 ads.txt 파일 생성이 필요한 이유\n\n무료 웹서버인 GitHub Pages로 웹서버를 운영한지도 \n1개월이 조금 더 지났습니다. \n기존에 운영하던 네이버 블로그와 티스토리 블로그와는 달리 \nGitHub Pages는 참 매력적이 점이 많이 있습니다.\n\n하루에 발행할 수 있는 페이지 수에 제한이 없고, \n이로 인해서 파이썬이나 배쉬와 같은 스크립트를 이용해서 \n자동으로 컨텐츠를 생성해 낼 수도 있습니다.\n\n또한, markdown 문법으로 시원시원하게 웹 페이지를 작성할 수 있습니다.\n\n많은 강점들을 가지고 있지만, 동시에 여러 단점들도 존재합니다.\n\n기존에 티스토리 블로그를 운영할 때에는 사이트맵 파일을 생성할 필요도 없고, \nrobots.txt 파일이나 ads.txt 같은 파일을 \n전혀 신경 쓸 필요가 없었습니다.\n\n하지만 GitHub Pages에서는 블로그 주인이 이런 파일들을 \n모두 신경써서 챙겨줘야 하는 단점이 있습니다.\n\n문제의 현상\n\n\n\nGitHub Pages를 생성한지 약 십여일만에 구글 애드센스 연동이 가능했고, \n티스토리에서 구글 애드센스를 연동했을 때는 경험하지 못한 \n생경한 경고 메시지를 만나게 되었습니다.\n\n구글 애드센스 페이지에 접속하면 “수익 손실 위험 - 수익에 심각한 영향을 미치지 않도록 사이트에서 발견된 ads.txt 파일 문제를 해결해야 합니다.”라는 경고 메시지가 떴습니다.\n\n문제의 원인\n\n웹 페이지의 루트 디렉토리에 ads.txt 파일이 존재하지 않아서 발생한 문제입니다.\n\n조치 방법\n\n웹 페이지의 루트 디렉토리에 ads.txt 파일을 생성하고, \n파일 안에 아래와 같은 형식으로 입력해주면 됩니다.\n\ngoogle.com, pub-XXXXXXXXXXXXXXXX, DIRECT, XXXXXXXXXXXXXXXX\n\n\n참고로 ads.txt 파일에 포함되어야 할 내용은 \n구글 애드센스에서 친절하게 제공합니다.\n\n문제 해결 확인\n\n위와 같이 웹 페이지의 루트 디렉토리에 ads.txt 파일을 \n구글 애드센스에서 가이드한 포맷으로 작성해줬더니 문제가 해결되었습니다.\n\n그리고 지금 아주 미미하지만 구글 애드센스 수익이 발생하기 시작했습니다.\n\n결론\n\n구글 애드센스에서 ads.txt 파일 관련 경고 메시지가 뜨면, \n구글 애드센스에서 제공하는 ads.txt 파일을 \n웹 페이지의 루트 디렉토리에 업로드해주면 깔끔하게 해결됩니다.\n\n"]
Title : 라즈베리파이4B 리모컨 입력 처리 방법 (Ubuntu 21.10)
URL : /010_raspberry/002-rpi4-ir-receiver-ubuntu-21-10.html
Description : 라즈베리파이4B에서 리모컨 입력 받아서 처리하는 방법 (Ubuntu 21.10)
Content : 라즈베리파이를 이용해서 프로젝트를 진행하거나,
스터디를 진행함에 있어서 가장 쉽게 접근할 수 있고,
가장 손쉽게 정보를 얻을 수 있는 방법은 라즈비안을 사용하는 것입니다.

하지만 제게 가장 익숙한 OS인 Ubuntu Linux를 포기할 수 없어서,
라즈베리파이4B(rpi4)에 Ubuntu Linux 21.10을 설치했습니다.

IR 센서를 이용해서 리모컨 입력을 받아서 처리하는 작업을 진행해보았습니다.
대부분의 자료들이 라즈비안 베이스라서 Ubuntu Linux에서는
어떻게 설정해야 하는지에 대한 정보를 얻기가 쉽지는 않았습니다.

본 페이지에서는 Ubuntu Linux 21.10에서 VS 1838B IR 센서를 이용해서
리모컨 입력을 받는 방법에 대해서 설명하고자 합니다.



부디 여러분들이 찾는 도움이 되는 자료이기를 바랍니다.

환경




구분
세부 내용
비고




IR 센서
VS 1838B
 


H/W
Rpi4
 


OS
Ubuntu Linux 21.10
 




OS 버전을 확인하려면 lsb_release -a를 입력하시면 됩니다.

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 21.10
Release: 21.10
Codename: impish


제 RPi4에는 Ubuntu Linux 21.10이 설치되어 있습니다.

하드웨어 연결

하드웨어 구성은 아주 간단합니다.
VS 1838B라는 리모컨 수신 모듈은
동작 전압이 3.3V이기 때문에 별도로 전압을 강하해줄 필요 없이
라즈베리파이에 바로 연결이 가능합니다.

VS 1838B를 정면에서 바라보았을 때,
가장 왼쪽부터 Output, GND, Vcc 입니다.






핀번호
신호
비고




1
Output
17번 핀에 연결


2
GND
 


3
Vcc
3.3V




회로 구성이 올바른지 확인 방법 #1

Output에 3.3V LED를 연결하면 리모컨 버튼을 눌렀을 때,
LED가 아주 빠르게 깜빡거리는 것을 확인할 수 있습니다.
그러면 회로 구성이 올바르게 되었다는 것을 알 수 있습니다.

회로 구성이 올바른지 확인 방법 #2

또한 회로 연결이 제대로 되었는지 확인하는 추가적인 방법은
파이썬으로 GPIO17번 포트를 연속적으로 읽어보는 방법이 있습니다.

이 때, 리모컨 버튼을 눌렀을 때 GPIO17번으로 읽은 입력이 변화한다면
회로 연결이 제대로 구성되었다고 추측할 수 있겠습니다.

lirc 설치 및 설정

지금부터는 lirc 패키지를 설치하고, 설정 파일들을 편집해주는 작업입니다.


lirc 패키지 설치
/etc/lirc/lirc_options.conf 파일 편집
/boot/firmware/config.txt 파일 편집
/etc/modules 파일 편집


lirc 패키지 설치

아래 명령으로 lirc 패키지를 설치합니다.

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install lirc


/etc/lirc/lirc_options.conf 파일 편집

아래 명령으로 /etc/lirc/lirc_options.conf 파일을 편집해줍니다.

$ sudo vi /etc/lirc/lirc_options.conf


파일 내용 중에 아래 2개 라인을 수정해줍니다.

driver = default
device = /dev/lirc0


/boot/firmware/config.txt 파일 편집

아래 명령으로 /boot/firmware/config.txt 파일을 편집합니다.

$ sudo vi /boot/firmware/config.txt


dtoverlay=vc4-kms-v3d로 되어 있는데 주석처리하고,
dtoverlay=gpio-ir,gpio_pin=17를 추가로 입력해줍니다.

어떤 기사를 보면 /boot/config.txt 파일을 편집하라고 하는데,
Ubuntu 21.10 버전에서는 해당 파일이 없습니다.

/boot/config.txt 파일이 아니라
/boot/firmware/config.txt 파일을 편집하셔야 합니다.

/etc/modules 파일 편집~

어떤 기사를 보면 /etc/modules 파일을 편집하라는 내용이 있는데,
제 경우는 이것이 오히려 부팅 불량을 야기하였습니다.

아래와 같이 /etc/modules 파일을 편집한 이후로
LED가 7번 깜빡거리면서 부팅하지 못하는 부팅 불량을 야기했습니다.

이 때문에 이 설정을 원복(주석 처리)했더니 부팅이 정상적으로 이뤄졌습니다.
또한, 이 파일을 편집하지 않았음에도 불구하고 동작에 전혀 문제가 없었습니다.
특별한 경우가 아니라면 아래 과정을 생략하시기 바랍니다.

아래 명령으로 /etc/modules 파일을 편집합니다.

$ sudo vi /etc/modules


제 경우는 텅 비어있는데, 아래와 같이 2줄을 입력해줬습니다.

lirc
lirc_rpi gpio_in_pin=17


재부팅 후 lirc 확인

재부팅 이후에 mode2 명령을 실행시킨 이후에
리모컨을 눌러보면 아래와 같은 메시지가 출력됩니다.

아래와 같이 sudo mode2 -d /dev/lirc0를 입력합니다.

$ sudo mode2 -d /dev/lirc0


입력한 이후에 리모컨 버튼을 누르면 화면에 뭔가 반응이 있습니다.

Using driver default on device /dev/lirc0
Trying device: /dev/lirc0
Using device: /dev/lirc0
Running as regular user boyinblue
pulse 224
timeout 130791
pulse 146
timeout 131392
pulse 146


리모컨 설정파일 다운로드 방법

이 단계까지 왔다면 리모컨 수신 모듈이 정상 동작하고 있다는 것입니다.
다음 단계는 리모컨을 학습시키거나 이미 학습된 리모컨 설정파일을
다운로드 하는 단계입니다.

아래 경로로 접속하면 다양한 제조사의 리모컨 설정 파일들을
다운로드 하실 수 있습니다.

http://lirc.sourceforge.net/remotes/

다운로드한 설정파일은 /etc/lirc/lircd.conf.d 디렉토리
안에 .conf 확장자로 저장하시면 됩니다.

리모컨 설정파일은 여러개를 저장해도 무관합니다.

저장한 이후에 lirc 서비스를 재시작합니다.

$ service lircd restart


서비스를 재시작한 이후에 서비스 로그를 살펴보면 아래와 같이
다수의 리모컨 설정 파일들이 로드된 것을 확인할 수 있습니다.

$ service lircd status


제가 /etc/lirc/lircd.conf.d/ 경로에 저장해둔
Samsung-SIRS30, Samsung_SMT-10 등의
리모컨 설정파일들이 로드된 것을 확인할 수 있습니다.

Apr 13 03:41:54 RpiHome lircd-0.10.1[10467]: Info: Using remote: Samsung-SIRS30>
Apr 13 03:41:54 RpiHome lircd-0.10.1[10467]: Info: Using remote: Samsung_SMT-10>
Apr 13 03:41:54 RpiHome lircd-0.10.1[10467]: Info: Using remote: Samsung.
Apr 13 03:41:54 RpiHome lircd-0.10.1[10467]: Info: Using remote: Terratec.


아까 /etc/lirc/lircd.conf.d 디렉토리에
여러 설정파일들을 넣어두어도 된다고 말씀드렸습니다.

실제로 /etc/lirc/lircd.conf 파일을 열어보면
include "lircd.conf.d/*.conf" 구문을 확인할 수 있습니다.

$ cat lircd.conf
# Populated config files can be found at http://sf.net/p/lirc-remotes. The
# irdb-get(1) and lirc-setup(1) tools can be used to search and download
# config files.
#
# From 0.9.2 config files could just be dropped as-is in the lircd.conf.d
# directory and be included by this file.

include "lircd.conf.d/*.conf"


리모컨 학습하는 방법

리모컨 설정 파일을 다운로드 받는 방법도 있지만,
해당하는 리모컨 설정 파일이 존재하지 않을 경우에는
리모컨 신호를 직접 학습시키는 방법이 있습니다.

리모컨 학습이 쉽지 않는 경우가 많이 발생합니다.
그 이유는, lircd 서비스를 제대로 종료시키지 않아서
발생하는 경우가 많습니다.

아래의 명령을 실행하여 lircd 서비스를 종료해줍니다.

$ sudo systemctl stop lircd.service
$ sudo systemctl stop lircd.socket


lircd.service 서비스를 종료시키더라도,
lircd.socket 서비스에 의해서 다시 서비스가
활성화될 수 있으므로, 반드시 lircd.socket 서비스 까지
종료시킨 이후에 리모컨 학습을 시도하시기 바랍니다.

이제 본격적으로 리모컨 학습을 시작할 차례입니다.
sudo irrecord -n -d /dev/lirc0 my_remote.conf 명령으로
리모컨을 학습시킨 후 my_remote.conf 파일에 저장할 수 있습니다.

$ sudo irrecord -n -d /dev/lirc0 my_remote.conf


아래는 제가 리모컨을 학습시킨 로그입니다.

$ sudo irrecord -n -d /dev/lirc0 lircd.conf
Running as regular user parksejin
Using driver default on device /dev/lirc0

irrecord - application for recording IR-codes for usage with lirc
Copyright (C) 1998,1999 Christoph Bartelmus(lirc@bartelmus.de)

This program will record the signals from your remote control
and create a config file for lircd.

A proper config file for lircd is maybe the most vital part of this
package, so you should invest some time to create a working config
file. Although I put a good deal of effort in this program it is often
not possible to automatically recognize all features of a remote
control. Often short-comings of the receiver hardware make it nearly
impossible. If you have problems to create a config file READ THE
DOCUMENTATION at https://sf.net/p/lirc-remotes/wiki

If there already is a remote control of the same brand available at
http://sf.net/p/lirc-remotes you might want to try using such a
remote as a template. The config files already contains all
parameters of the protocol used by remotes of a certain brand and
knowing these parameters makes the job of this program much
easier. There are also template files for the most common protocols
available. Templates can be downloaded using irdb-get(1). You use a
template file by providing the path of the file as a command line
parameter.

Please take the time to finish the file as described in
https://sourceforge.net/p/lirc-remotes/wiki/Checklist/ an send it
to <lirc@bartelmus.de> so it can be made available to others.

Press RETURN to continue.

Checking for ambient light creating too much disturbances.
Please don't press any buttons, just wait a few seconds...

No significant noise (received 0 bytes)

Enter name of remote (only ascii, no spaces) :samsung
Using samsung.lircd.conf as output filename

Now start pressing buttons on your remote control.

It is very important that you press many different buttons randomly
and hold them down for approximately one second. Each button should
generate at least one dot but never more than ten dots of output.
Don't stop pressing buttons until two lines of dots (2x80) have
been generated.

Press RETURN now to start recording.
................................................................................
Got gap (47137 us)}

Please keep on pressing buttons like described above.
...............................................................................

Please enter the name for the next button (press <ENTER> to finish recording)
KEY_STOP

Now hold down button "KEY_STOP".


학습이 완벽하지 않더라도 설정 파일을 열어보면
리모컨의 신호의 비트수와 주파수 등을 확인할 수 있습니다.

begin remote

name DVD_PLAYER
bits 32
flags SPACE_ENC|CONST_LENGTH
eps 30
aeps 100

header 4486 4580
one 502 1746
zero 502 621
ptrail 499
gap 108440
toggle_bit_mask 0x0
frequency 38000

begin codes
end codes

end remote


제가 학습을 시켜본 삼성 TV 리모컨은 비트수가 32비트이고,
주파수는 38KHz 입니다.

혹시 리모컨 학습이 완료되지 못했을 경우에는
위의 비트수와 주파수 정보만 가지고 여기에 맞는 리모컨 설정 파일을
위에서 언급한 홈페이지(http://lirc.sourceforge.net/remotes/)에서
찾으면 됩니다.

리모컨 테스트

리모컨 학습에 성공했거나, 혹은 적절한 리모컨 설정 파일을 받았다면,
그 다음 단계는 리모컨 신호를 테스트 하는 단계입니다.

irw 명령을 통해서 리모컨 신호가 제대로 인식되는지
테스트해볼 시간입니다.

$ irw
00000000e0e020df 00 KEY_1 Samsung_CS-25M6HNQ
00000000e0e020df 01 KEY_1 Samsung_CS-25M6HNQ
00000000e0e020df 00 KEY_1 Samsung_CS-25M6HNQ
00000000e0e0a05f 00 KEY_2 Samsung_CS-25M6HNQ
00000000e0e0a05f 01 KEY_2 Samsung_CS-25M6HNQ
00000000e0e0609f 00 KEY_3 Samsung_CS-25M6HNQ
00000000e0e0609f 01 KEY_3 Samsung_CS-25M6HNQ
00000000e0e0a05f 00 KEY_2 Samsung_CS-25M6HNQ
00000000e0e0a05f 01 KEY_2 Samsung_CS-25M6HNQ
00000000e0e020df 00 KEY_1 Samsung_CS-25M6HNQ
00000000e0e020df 01 KEY_1 Samsung_CS-25M6HNQ
00000000e0e020df 00 KEY_1 Samsung_CS-25M6HNQ
00000000e0e020df 01 KEY_1 Samsung_CS-25M6HNQ


irw 명령을 수행하면 위와 같이 어떤 키가
인식되었는지를 로그로 확인할 수 있습니다.

리모컨 신호를 받아서 처리하는 파이썬 예제

아래는 리모컨 신호를 받아서 처리하는 파이썬 예제입니다.
비동기(Non-Blocking) 방식과 동기(Blocking) 방식 2가지를 제공합니다.

#!/usr/bin/env python

import socket
import time

SOCKET_PATH = "/var/run/lirc/lircd"

sock = None
sync_mode = True

def init_irw(blocking = False):
global sock
global sync_mode

if blocking == True:
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
else:
sock = socket.socket(socket.AF_UNIX,
socket.SOCK_STREAM | socket.SOCK_NONBLOCK)

sync_mode = blocking

print ('Connect to lirc socket : ', SOCKET_PATH)
sock.connect(SOCKET_PATH)

def read_key_async():
try:
data = sock.recv(128)
except BlockingIOError:
return None

return data

def read_key_sync():
while True:
data = sock.recv(128)

if data:
data = data.strip()
return data

def read_key():
'''Get the next key pressed. Return keyname, updown.
'''
global sync_mode
if sync_mode:
data = read_key_sync()
else:
data = read_key_async()

if data:
words = data.split()
return words[2], words[1]

return '', ''

def main_sync():
init_irw(blocking = True)

while True:
keyname, updown = read_key()
print('%s (%s)' % (keyname, updown))

def main_async():
init_irw(blocking = False)

while True:
keyname, updown = read_key()
if keyname == '' and updown == '':
time.sleep(0.1)
continue
print('%s (%s)' % (keyname, updown))

if __name__ == '__main__':
#main_async()
main_sync()


동기화된 리턴 처리

동기화된 리턴의 경우 응답이 소켓으로 데이터가 수신될 때까지
함수가 리턴되지 않는 방식입니다.
즉, 데이터가 들어올 때까지 함수는 내부적으로 blocking 됩니다.

비동기 리턴 처리

비동기 함수의 경우 메시지 수신 여부와 관계없이
즉각적으로 함수가 리턴됩니다.

만약, 파이썬 프로그램이 여러가지 이벤트들을 처리해야 한다면,
리모컨 입력은 비동기 리턴 방식으로 처리를 해야 합니다.

코드 설명

우선 init_irw() 함수를 호출하여 초기화 합니다.
init_irw(blocking = True)로 호출하면
동기화된 리턴 방식으로 리모컨 메시지를 가져오게되고,
init_irw(blocking = False)로 호출하면
비동기 리턴 방식으로 리모컨 메시지를 가져오게 됩니다.

def init_irw(blocking = False):
global sock
global sync_mode

if blocking == True:
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
else:
sock = socket.socket(socket.AF_UNIX,
socket.SOCK_STREAM | socket.SOCK_NONBLOCK)

sync_mode = blocking

print ('Connect to lirc socket : ', SOCKET_PATH)
sock.connect(SOCKET_PATH)


비동기 리턴의 경우 socket.SOCK_NONBLOCK 속성을 지정하여
소켓을 생성하는 것을 확인할 수 있습니다.

lirc 소켓 파일 경로는 /var/run/lirc/lircd입니다.

def read_key_async():
try:
data = sock.recv(128)
except BlockingIOError:
return None

return data


비동기로 리모컨 신호를 수신을 시도하였는데,
소켓에 메시지가 없으면 BlockingIOError 예외가 발생합니다.
이 때에 스크립트가 종료되지 않고, 그저 None이 리턴될 수 있도록
적절하게 예외처리를 해줍니다.

while True:
keyname, updown = read_key()
if keyname == '' and updown == '':
time.sleep(0.1)
continue
print('%s (%s)' % (keyname, updown))


비동기 방식의 처리에서 메시지가 없을 경우 None이 리턴되므로
이 때에는 0.1초동안 기다렸다가 다시 소켓을 읽도록 하였습니다.

동기화된 리턴의 경우는 비동기 리턴보다 쉬운 개념이므로
설명을 생략하고자 합니다.

유용한 링크






Reading an IR Remote on a Raspberry Pi with LIRC
None









결론

Ubuntu Linux 21.10이 설치된 라즈베리파이4B에
IR 센서를 이용해서 리모컨 입력을 받는 방법에 대한 설명을 마칩니다.
["라즈베리파이를 이용해서 프로젝트를 진행하거나, \n스터디를 진행함에 있어서 가장 쉽게 접근할 수 있고, \n가장 손쉽게 정보를 얻을 수 있는 방법은 라즈비안을 사용하는 것입니다.\n\n하지만 제게 가장 익숙한 OS인 Ubuntu Linux를 포기할 수 없어서, \n라즈베리파이4B(rpi4)에 Ubuntu Linux 21.10을 설치했습니다.\n\nIR 센서를 이용해서 리모컨 입력을 받아서 처리하는 작업을 진행해보았습니다. \n대부분의 자료들이 라즈비안 베이스라서 Ubuntu Linux에서는 \n어떻게 설정해야 하는지에 대한 정보를 얻기가 쉽지는 않았습니다.\n\n본 페이지에서는 Ubuntu Linux 21.10에서 VS 1838B IR 센서를 이용해서 \n리모컨 입력을 받는 방법에 대해서 설명하고자 합니다.\n\n\n\n부디 여러분들이 찾는 도움이 되는 자료이기를 바랍니다.\n\n환경\n\n\n \n \n 구분\n 세부 내용\n 비고\n \n \n \n \n IR 센서\n VS 1838B\n  \n \n \n H/W\n Rpi4\n  \n \n \n OS\n Ubuntu Linux 21.10\n  \n \n \n\n\nOS 버전을 확인하려면 lsb_release -a를 입력하시면 됩니다.\n\n$ lsb_release -a\nNo LSB modules are available.\nDistributor ID:\tUbuntu\nDescription:\tUbuntu 21.10\nRelease:\t21.10\nCodename:\timpish\n\n\n제 RPi4에는 Ubuntu Linux 21.10이 설치되어 있습니다.\n\n하드웨어 연결\n\n하드웨어 구성은 아주 간단합니다. \nVS 1838B라는 리모컨 수신 모듈은 \n동작 전압이 3.3V이기 때문에 별도로 전압을 강하해줄 필요 없이 \n라즈베리파이에 바로 연결이 가능합니다.\n\nVS 1838B를 정면에서 바라보았을 때, \n가장 왼쪽부터 Output, GND, Vcc 입니다.\n\n\n\n\n \n \n 핀번호\n 신호\n 비고\n \n \n \n \n 1\n Output\n 17번 핀에 연결\n \n \n 2\n GND\n  \n \n \n 3\n Vcc\n 3.3V\n \n \n\n\n회로 구성이 올바른지 확인 방법 #1\n\nOutput에 3.3V LED를 연결하면 리모컨 버튼을 눌렀을 때, \nLED가 아주 빠르게 깜빡거리는 것을 확인할 수 있습니다. \n그러면 회로 구성이 올바르게 되었다는 것을 알 수 있습니다.\n\n회로 구성이 올바른지 확인 방법 #2\n\n또한 회로 연결이 제대로 되었는지 확인하는 추가적인 방법은 \n파이썬으로 GPIO17번 포트를 연속적으로 읽어보는 방법이 있습니다.\n\n이 때, 리모컨 버튼을 눌렀을 때 GPIO17번으로 읽은 입력이 변화한다면 \n회로 연결이 제대로 구성되었다고 추측할 수 있겠습니다.\n\nlirc 설치 및 설정\n\n지금부터는 lirc 패키지를 설치하고, 설정 파일들을 편집해주는 작업입니다.\n\n\n lirc 패키지 설치\n /etc/lirc/lirc_options.conf 파일 편집\n /boot/firmware/config.txt 파일 편집\n /etc/modules 파일 편집\n\n\nlirc 패키지 설치\n\n아래 명령으로 lirc 패키지를 설치합니다.\n\n$ sudo apt-get update\n$ sudo apt-get upgrade\n$ sudo apt-get install lirc\n\n\n/etc/lirc/lirc_options.conf 파일 편집\n\n아래 명령으로 /etc/lirc/lirc_options.conf 파일을 편집해줍니다.\n\n$ sudo vi /etc/lirc/lirc_options.conf\n\n\n파일 내용 중에 아래 2개 라인을 수정해줍니다.\n\ndriver = default\ndevice = /dev/lirc0\n\n\n/boot/firmware/config.txt 파일 편집\n\n아래 명령으로 /boot/firmware/config.txt 파일을 편집합니다.\n\n$ sudo vi /boot/firmware/config.txt\n\n\ndtoverlay=vc4-kms-v3d로 되어 있는데 주석처리하고, \ndtoverlay=gpio-ir,gpio_pin=17를 추가로 입력해줍니다.\n\n어떤 기사를 보면 /boot/config.txt 파일을 편집하라고 하는데, \nUbuntu 21.10 버전에서는 해당 파일이 없습니다.\n\n/boot/config.txt 파일이 아니라 \n/boot/firmware/config.txt 파일을 편집하셔야 합니다.\n\n/etc/modules 파일 편집~\n\n어떤 기사를 보면 /etc/modules 파일을 편집하라는 내용이 있는데, \n제 경우는 이것이 오히려 부팅 불량을 야기하였습니다.\n\n아래와 같이 /etc/modules 파일을 편집한 이후로 \nLED가 7번 깜빡거리면서 부팅하지 못하는 부팅 불량을 야기했습니다.\n\n이 때문에 이 설정을 원복(주석 처리)했더니 부팅이 정상적으로 이뤄졌습니다. \n또한, 이 파일을 편집하지 않았음에도 불구하고 동작에 전혀 문제가 없었습니다. \n특별한 경우가 아니라면 아래 과정을 생략하시기 바랍니다.\n\n아래 명령으로 /etc/modules 파일을 편집합니다.\n\n$ sudo vi /etc/modules\n\n\n제 경우는 텅 비어있는데, 아래와 같이 2줄을 입력해줬습니다.\n\nlirc\nlirc_rpi gpio_in_pin=17\n\n\n재부팅 후 lirc 확인\n\n재부팅 이후에 mode2 명령을 실행시킨 이후에 \n리모컨을 눌러보면 아래와 같은 메시지가 출력됩니다.\n\n아래와 같이 sudo mode2 -d /dev/lirc0를 입력합니다.\n\n$ sudo mode2 -d /dev/lirc0\n\n\n입력한 이후에 리모컨 버튼을 누르면 화면에 뭔가 반응이 있습니다.\n\nUsing driver default on device /dev/lirc0\nTrying device: /dev/lirc0\nUsing device: /dev/lirc0\nRunning as regular user boyinblue\npulse 224\ntimeout 130791\npulse 146\ntimeout 131392\npulse 146\n\n\n리모컨 설정파일 다운로드 방법\n\n이 단계까지 왔다면 리모컨 수신 모듈이 정상 동작하고 있다는 것입니다. \n다음 단계는 리모컨을 학습시키거나 이미 학습된 리모컨 설정파일을 \n다운로드 하는 단계입니다.\n\n아래 경로로 접속하면 다양한 제조사의 리모컨 설정 파일들을 \n다운로드 하실 수 있습니다.\n\nhttp://lirc.sourceforge.net/remotes/\n\n다운로드한 설정파일은 /etc/lirc/lircd.conf.d 디렉토리 \n안에 .conf 확장자로 저장하시면 됩니다.\n\n리모컨 설정파일은 여러개를 저장해도 무관합니다.\n\n저장한 이후에 lirc 서비스를 재시작합니다.\n\n$ service lircd restart\n\n\n서비스를 재시작한 이후에 서비스 로그를 살펴보면 아래와 같이 \n다수의 리모컨 설정 파일들이 로드된 것을 확인할 수 있습니다.\n\n$ service lircd status\n\n\n제가 /etc/lirc/lircd.conf.d/ 경로에 저장해둔 \nSamsung-SIRS30, Samsung_SMT-10 등의 \n리모컨 설정파일들이 로드된 것을 확인할 수 있습니다.\n\nApr 13 03:41:54 RpiHome lircd-0.10.1[10467]: Info: Using remote: Samsung-SIRS30>\nApr 13 03:41:54 RpiHome lircd-0.10.1[10467]: Info: Using remote: Samsung_SMT-10>\nApr 13 03:41:54 RpiHome lircd-0.10.1[10467]: Info: Using remote: Samsung.\nApr 13 03:41:54 RpiHome lircd-0.10.1[10467]: Info: Using remote: Terratec.\n\n\n아까 /etc/lirc/lircd.conf.d 디렉토리에 \n여러 설정파일들을 넣어두어도 된다고 말씀드렸습니다.\n\n실제로 /etc/lirc/lircd.conf 파일을 열어보면 \ninclude \"lircd.conf.d/*.conf\" 구문을 확인할 수 있습니다.\n\n$ cat lircd.conf\n# Populated config files can be found at http://sf.net/p/lirc-remotes. The\n# irdb-get(1) and lirc-setup(1) tools can be used to search and download\n# config files.\n#\n# From 0.9.2 config files could just be dropped as-is in the lircd.conf.d\n# directory and be included by this file.\n\ninclude \"lircd.conf.d/*.conf\"\n\n\n리모컨 학습하는 방법\n\n리모컨 설정 파일을 다운로드 받는 방법도 있지만, \n해당하는 리모컨 설정 파일이 존재하지 않을 경우에는 \n리모컨 신호를 직접 학습시키는 방법이 있습니다.\n\n리모컨 학습이 쉽지 않는 경우가 많이 발생합니다. \n그 이유는, lircd 서비스를 제대로 종료시키지 않아서 \n발생하는 경우가 많습니다.\n\n아래의 명령을 실행하여 lircd 서비스를 종료해줍니다.\n\n$ sudo systemctl stop lircd.service\n$ sudo systemctl stop lircd.socket\n\n\nlircd.service 서비스를 종료시키더라도, \nlircd.socket 서비스에 의해서 다시 서비스가 \n활성화될 수 있으므로, 반드시 lircd.socket 서비스 까지 \n종료시킨 이후에 리모컨 학습을 시도하시기 바랍니다.\n\n이제 본격적으로 리모컨 학습을 시작할 차례입니다. \nsudo irrecord -n -d /dev/lirc0 my_remote.conf 명령으로 \n리모컨을 학습시킨 후 my_remote.conf 파일에 저장할 수 있습니다.\n\n$ sudo irrecord -n -d /dev/lirc0 my_remote.conf\n\n\n아래는 제가 리모컨을 학습시킨 로그입니다.\n\n$ sudo irrecord -n -d /dev/lirc0 lircd.conf\nRunning as regular user parksejin\nUsing driver default on device /dev/lirc0\n\nirrecord - application for recording IR-codes for usage with lirc\nCopyright (C) 1998,1999 Christoph Bartelmus(lirc@bartelmus.de)\n\nThis program will record the signals from your remote control\nand create a config file for lircd.\n\nA proper config file for lircd is maybe the most vital part of this\npackage, so you should invest some time to create a working config\nfile. Although I put a good deal of effort in this program it is often\nnot possible to automatically recognize all features of a remote\ncontrol. Often short-comings of the receiver hardware make it nearly\nimpossible. If you have problems to create a config file READ THE\nDOCUMENTATION at https://sf.net/p/lirc-remotes/wiki\n\nIf there already is a remote control of the same brand available at\nhttp://sf.net/p/lirc-remotes you might want to try using such a\nremote as a template. The config files already contains all\nparameters of the protocol used by remotes of a certain brand and\nknowing these parameters makes the job of this program much\neasier. There are also template files for the most common protocols\navailable. Templates can be downloaded using irdb-get(1). You use a\ntemplate file by providing the path of the file as a command line\nparameter.\n\nPlease take the time to finish the file as described in\nhttps://sourceforge.net/p/lirc-remotes/wiki/Checklist/ an send it\nto <lirc@bartelmus.de> so it can be made available to others.\n\nPress RETURN to continue.\n\nChecking for ambient light creating too much disturbances.\nPlease don't press any buttons, just wait a few seconds...\n\nNo significant noise (received 0 bytes)\n\nEnter name of remote (only ascii, no spaces) :samsung\nUsing samsung.lircd.conf as output filename\n\nNow start pressing buttons on your remote control.\n\nIt is very important that you press many different buttons randomly\nand hold them down for approximately one second. Each button should\ngenerate at least one dot but never more than ten dots of output.\nDon't stop pressing buttons until two lines of dots (2x80) have\nbeen generated.\n\nPress RETURN now to start recording.\n................................................................................\nGot gap (47137 us)}\n\nPlease keep on pressing buttons like described above.\n...............................................................................\n\nPlease enter the name for the next button (press <ENTER> to finish recording)\nKEY_STOP\n\nNow hold down button \"KEY_STOP\".\n\n\n학습이 완벽하지 않더라도 설정 파일을 열어보면 \n리모컨의 신호의 비트수와 주파수 등을 확인할 수 있습니다.\n\nbegin remote\n\n name DVD_PLAYER\n bits 32\n flags SPACE_ENC|CONST_LENGTH\n eps 30\n aeps 100\n\n header 4486 4580\n one 502 1746\n zero 502 621 \n ptrail 499\n gap 108440\n toggle_bit_mask 0x0 \n frequency 38000\n\n begin codes\n end codes\n\nend remote\n\n\n제가 학습을 시켜본 삼성 TV 리모컨은 비트수가 32비트이고, \n주파수는 38KHz 입니다.\n\n혹시 리모컨 학습이 완료되지 못했을 경우에는 \n위의 비트수와 주파수 정보만 가지고 여기에 맞는 리모컨 설정 파일을 \n위에서 언급한 홈페이지(http://lirc.sourceforge.net/remotes/)에서 \n찾으면 됩니다.\n\n리모컨 테스트\n\n리모컨 학습에 성공했거나, 혹은 적절한 리모컨 설정 파일을 받았다면, \n그 다음 단계는 리모컨 신호를 테스트 하는 단계입니다.\n\nirw 명령을 통해서 리모컨 신호가 제대로 인식되는지 \n테스트해볼 시간입니다.\n\n$ irw\n00000000e0e020df 00 KEY_1 Samsung_CS-25M6HNQ\n00000000e0e020df 01 KEY_1 Samsung_CS-25M6HNQ\n00000000e0e020df 00 KEY_1 Samsung_CS-25M6HNQ\n00000000e0e0a05f 00 KEY_2 Samsung_CS-25M6HNQ\n00000000e0e0a05f 01 KEY_2 Samsung_CS-25M6HNQ\n00000000e0e0609f 00 KEY_3 Samsung_CS-25M6HNQ\n00000000e0e0609f 01 KEY_3 Samsung_CS-25M6HNQ\n00000000e0e0a05f 00 KEY_2 Samsung_CS-25M6HNQ\n00000000e0e0a05f 01 KEY_2 Samsung_CS-25M6HNQ\n00000000e0e020df 00 KEY_1 Samsung_CS-25M6HNQ\n00000000e0e020df 01 KEY_1 Samsung_CS-25M6HNQ\n00000000e0e020df 00 KEY_1 Samsung_CS-25M6HNQ\n00000000e0e020df 01 KEY_1 Samsung_CS-25M6HNQ\n\n\nirw 명령을 수행하면 위와 같이 어떤 키가 \n인식되었는지를 로그로 확인할 수 있습니다.\n\n리모컨 신호를 받아서 처리하는 파이썬 예제\n\n아래는 리모컨 신호를 받아서 처리하는 파이썬 예제입니다. \n비동기(Non-Blocking) 방식과 동기(Blocking) 방식 2가지를 제공합니다.\n\n#!/usr/bin/env python\n\nimport socket\nimport time\n\nSOCKET_PATH = \"/var/run/lirc/lircd\"\n\nsock = None\nsync_mode = True\n\ndef init_irw(blocking = False):\n global sock\n global sync_mode\n\n if blocking == True:\n sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)\n else:\n sock = socket.socket(socket.AF_UNIX,\n socket.SOCK_STREAM | socket.SOCK_NONBLOCK)\n\n sync_mode = blocking\n\n print ('Connect to lirc socket : ', SOCKET_PATH)\n sock.connect(SOCKET_PATH)\n\ndef read_key_async():\n try:\n data = sock.recv(128)\n except BlockingIOError:\n return None\n \n return data\n\ndef read_key_sync():\n while True:\n data = sock.recv(128)\n \n if data:\n data = data.strip()\n return data\n\ndef read_key():\n '''Get the next key pressed. Return keyname, updown.\n '''\n global sync_mode\n if sync_mode:\n data = read_key_sync()\n else:\n data = read_key_async()\n\n if data:\n words = data.split()\n return words[2], words[1]\n\n return '', ''\n\ndef main_sync():\n init_irw(blocking = True)\n\n while True:\n keyname, updown = read_key()\n print('%s (%s)' % (keyname, updown))\n\ndef main_async():\n init_irw(blocking = False)\n\n while True:\n keyname, updown = read_key()\n if keyname == '' and updown == '':\n time.sleep(0.1)\n continue\n print('%s (%s)' % (keyname, updown))\n\nif __name__ == '__main__':\n #main_async()\n main_sync()\n\n\n동기화된 리턴 처리\n\n동기화된 리턴의 경우 응답이 소켓으로 데이터가 수신될 때까지 \n함수가 리턴되지 않는 방식입니다. \n즉, 데이터가 들어올 때까지 함수는 내부적으로 blocking 됩니다.\n\n비동기 리턴 처리\n\n비동기 함수의 경우 메시지 수신 여부와 관계없이 \n즉각적으로 함수가 리턴됩니다.\n\n만약, 파이썬 프로그램이 여러가지 이벤트들을 처리해야 한다면, \n리모컨 입력은 비동기 리턴 방식으로 처리를 해야 합니다.\n\n코드 설명\n\n우선 init_irw() 함수를 호출하여 초기화 합니다. \ninit_irw(blocking = True)로 호출하면 \n동기화된 리턴 방식으로 리모컨 메시지를 가져오게되고, \ninit_irw(blocking = False)로 호출하면 \n비동기 리턴 방식으로 리모컨 메시지를 가져오게 됩니다.\n\ndef init_irw(blocking = False):\n global sock\n global sync_mode\n\n if blocking == True:\n sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)\n else:\n sock = socket.socket(socket.AF_UNIX,\n socket.SOCK_STREAM | socket.SOCK_NONBLOCK)\n\n sync_mode = blocking\n\n print ('Connect to lirc socket : ', SOCKET_PATH)\n sock.connect(SOCKET_PATH)\n\n\n비동기 리턴의 경우 socket.SOCK_NONBLOCK 속성을 지정하여 \n소켓을 생성하는 것을 확인할 수 있습니다.\n\nlirc 소켓 파일 경로는 /var/run/lirc/lircd입니다.\n\ndef read_key_async():\n try:\n data = sock.recv(128)\n except BlockingIOError:\n return None\n\n return data\n\n\n비동기로 리모컨 신호를 수신을 시도하였는데, \n소켓에 메시지가 없으면 BlockingIOError 예외가 발생합니다. \n이 때에 스크립트가 종료되지 않고, 그저 None이 리턴될 수 있도록 \n적절하게 예외처리를 해줍니다.\n\n while True:\n keyname, updown = read_key()\n if keyname == '' and updown == '':\n time.sleep(0.1)\n continue\n print('%s (%s)' % (keyname, updown))\n\n\n비동기 방식의 처리에서 메시지가 없을 경우 None이 리턴되므로 \n이 때에는 0.1초동안 기다렸다가 다시 소켓을 읽도록 하였습니다.\n\n동기화된 리턴의 경우는 비동기 리턴보다 쉬운 개념이므로 \n설명을 생략하고자 합니다.\n\n유용한 링크\n\n\n\n\n \n \n Reading an IR Remote on a Raspberry Pi with LIRC\n None\n \n \n \n \n \n \n\n\n\n결론\n\nUbuntu Linux 21.10이 설치된 라즈베리파이4B에 \nIR 센서를 이용해서 리모컨 입력을 받는 방법에 대한 설명을 마칩니다.\n"]
Title : 파이썬 vim 띄워쓰기 설정 방법
URL : /004_python/004-python-vim-setting.html
Description : vim을 이용하여 파이썬 스크립트 편집시에 띄워쓰기 설정 방법
Content : 파이썬은 띄워쓰기에 아주 민감한 프로그래밍 언어이다.
이 페이지에서는 vim을 이용하여 파이썬 스크립트를 작성할 때
띄워쓰기 오류를 줄이기 위한 설정 방법을 제공한다.

C언어나 Java 언어에서의 중괄호

파이썬의 띄워쓰기 설정에 대해서 이야기하기에 앞서서
왜 유독 파이썬에서만 띄워쓰기가 민감한지에 대해서 설정하겠다.

기존의 C나 Java에서는 {와 </code>}</code>와 같은
중괄호를 이용해서 for 구문 혹은 if 구문 등의 시작과 끝을 정의했다.

if( a == 10 )
{
b = a;
}


위는 C언어에서 사용하는 중괄호의 예이다.
if문의 시작과 끝을 알려주는 중괄호가 2개의 라인에 들어가기 때문에
프로그래머 입장에서는 중괄호 입력이 제법 성가실 수 있다.

또한 중괄호가 너무 많아서 코드가 컴팩트해보이지 못하기 때문에
아래와 같이 중괄호를 입력하도록 코딩 규칙을 만들어 놓은
프로젝트도 존재한다.

if( a == 10 ) {
b = 1;
}


위와 같이 코드 블록의 시작을 알리는 {를
if 구문의 끝에 위치시키면서 코드를 좀 더 간결하게 만들 수도 있다.

위의 2가지 코딩 스타일은 프로그래머마다 호불호가 갈리기 때문에
서로 다른 스타일로 코딩하는 프로그래머가 하나의 과제를 진행하다보면
하나의 프로젝트에 여러 스타일의 코딩이 섞이게 된다.

파이썬에서의 띄워쓰기는 문법의 일부이다.

하지만 파이썬은 띄워쓰기(indent)를 통해서 코드 블록의
시작과 끝을 알려주는 방식이다.

프로그래머는 기존의 {와 } 따위의
중괄호를 입력하지 않아도 되기 때문에 가독성도 괜찮고
시원시원하게 코드를 작성해 나갈 수 있는 장점이 있다.

반면, 스페이스와 텝을 혼용할 경우 띄워쓰기 오류에 의해서
원하지 않은 결과를 얻을 수도 있고,
실행시에 수많은 띄워쓰기 에러 메시지를 만날 수 있다.

vim 패키지 설치

처음 Ubuntu Linux를 설치하면 vi 명령이 제법 불편하다.
키보드의 방향키가 제대로 동작하지 않는다.
기본적인 vi의 경우 방향키 대신에 ‘h’, ‘j’, ‘k’, ‘l’ 등의 키로
커서를 이동시키도록 되어 있기 때문이다.

vi 방향키


‘h’ : 왼쪽으로 이동
‘j’ : 아래로 이동
‘k’ : 위로 이동
‘l’ : 오른쪽으로 이동


일단 방향키부터 무척 불편하기 때문에 vim 패키지를 설치한다.

$ sudo apt-get install vim

vim 패키지를 설치한 이후에 vi 편집기를 열면
키보드의 방향키가 정상적으로 잘 인식되는 것을 알 수 있다.

파이썬 코딩을 위한 vim 설정

파이썬 코딩을 위한 vim 설정의 핵심은
Tab을 Space로 바꿔주는 것에 있다.

vim 설정 파일의 경로는 ~/.vimrc다.
선호하는 편집기로 ~/.vimrc 파일을 편집해준다.

$ vi ~/.vimrc


syntax on
filetype indent plugin on
set tabstop=4
set expandtab!
set softtabstop=4
set nu

let g:python_recommended_style=0


위의 설정은 필자가 선호하는 vim 설정이다.
그런데 다소 이해가 되지 않는 부분이 있을 것이다.

파이썬에서는 Tab을 Space로
변경해주는 것이 핵심이라고 하면서
set expandtab! 설정을 통해서
오히려 텝을 스페이스로 바꿔주지 않도록 하고 있다.

필자는 기본적으로 C언어 작업과 파이썬을 병행한다.
또한 C언어로 코딩할때 텝은 4칸을 선호한다.

따라서 필자가 C언어로 코딩할때는 텝을 그대로 사용 가능하고,
텝은 공백 4칸으로 설정이 된다.

반면, 파이썬으로 코딩할때는 아래 구문에 의해서
텝이 자동으로 스페이스로 변환된다.

let g:python_recommended_style=0

위의 코드 이전에 설정한 값들이
let g:python_recommended_style=0 설정에 의해서
overwrite될 수 있음을 유의한다.

예를들면, set expand tab!과 같은 설정은
python 스크립트 편집시에는 전혀 먹히지 않는다는 것이다.

python syntax 파일 다운로드 방법

python syntax 파일은 아래 위치에서 다운로드 받을 수 있다.

https://www.vim.org/scripts/script.php?script_id=790

python.vim 파일은 ~/.vim/syntax 경로에 저장하면 된다.

위의 페이지에 접속하는게 번거롭다면 아래 링크에서 다운로드 받으면 된다.

python.vim

아래의 명령으로 한 번에 다운로드가 가능하다.

$ mkdir -p ~/.vim/syntax
$ wget -O ~/.vim/syntax/syntax.vim https://boyinblue.github.io/004_python/python.vim


결론

파이썬은 띄워쓰기에 아주 민감한 언어이다.
그 이유는 파이썬에서의 씌워쓰기는 문법의 일부이기 때문이다.

vim에서 파이썬 스크립트를 편리하게 편집하기 위한
설정 방법에 대해서도 언급하였다.
["파이썬은 띄워쓰기에 아주 민감한 프로그래밍 언어이다. \n이 페이지에서는 vim을 이용하여 파이썬 스크립트를 작성할 때 \n띄워쓰기 오류를 줄이기 위한 설정 방법을 제공한다.\n\nC언어나 Java 언어에서의 중괄호\n\n파이썬의 띄워쓰기 설정에 대해서 이야기하기에 앞서서 \n왜 유독 파이썬에서만 띄워쓰기가 민감한지에 대해서 설정하겠다.\n\n기존의 C나 Java에서는 {와 </code>}</code>와 같은 \n중괄호를 이용해서 for 구문 혹은 if 구문 등의 시작과 끝을 정의했다.\n\nif( a == 10 )\n{\n b = a;\n}\n\n\n위는 C언어에서 사용하는 중괄호의 예이다. \nif문의 시작과 끝을 알려주는 중괄호가 2개의 라인에 들어가기 때문에 \n프로그래머 입장에서는 중괄호 입력이 제법 성가실 수 있다.\n\n또한 중괄호가 너무 많아서 코드가 컴팩트해보이지 못하기 때문에 \n아래와 같이 중괄호를 입력하도록 코딩 규칙을 만들어 놓은 \n프로젝트도 존재한다.\n\nif( a == 10 ) {\n b = 1;\n}\n\n\n위와 같이 코드 블록의 시작을 알리는 {를 \nif 구문의 끝에 위치시키면서 코드를 좀 더 간결하게 만들 수도 있다.\n\n위의 2가지 코딩 스타일은 프로그래머마다 호불호가 갈리기 때문에 \n서로 다른 스타일로 코딩하는 프로그래머가 하나의 과제를 진행하다보면 \n하나의 프로젝트에 여러 스타일의 코딩이 섞이게 된다.\n\n파이썬에서의 띄워쓰기는 문법의 일부이다.\n\n하지만 파이썬은 띄워쓰기(indent)를 통해서 코드 블록의 \n시작과 끝을 알려주는 방식이다.\n\n프로그래머는 기존의 {와 } 따위의 \n중괄호를 입력하지 않아도 되기 때문에 가독성도 괜찮고 \n시원시원하게 코드를 작성해 나갈 수 있는 장점이 있다.\n\n반면, 스페이스와 텝을 혼용할 경우 띄워쓰기 오류에 의해서 \n원하지 않은 결과를 얻을 수도 있고, \n실행시에 수많은 띄워쓰기 에러 메시지를 만날 수 있다.\n\nvim 패키지 설치\n\n처음 Ubuntu Linux를 설치하면 vi 명령이 제법 불편하다. \n키보드의 방향키가 제대로 동작하지 않는다. \n기본적인 vi의 경우 방향키 대신에 ‘h’, ‘j’, ‘k’, ‘l’ 등의 키로\n커서를 이동시키도록 되어 있기 때문이다.\n\nvi 방향키\n\n\n ‘h’ : 왼쪽으로 이동\n ‘j’ : 아래로 이동\n ‘k’ : 위로 이동\n ‘l’ : 오른쪽으로 이동\n\n\n일단 방향키부터 무척 불편하기 때문에 vim 패키지를 설치한다.\n\n$ sudo apt-get install vim\n\nvim 패키지를 설치한 이후에 vi 편집기를 열면 \n키보드의 방향키가 정상적으로 잘 인식되는 것을 알 수 있다.\n\n파이썬 코딩을 위한 vim 설정\n\n파이썬 코딩을 위한 vim 설정의 핵심은 \nTab을 Space로 바꿔주는 것에 있다.\n\nvim 설정 파일의 경로는 ~/.vimrc다. \n선호하는 편집기로 ~/.vimrc 파일을 편집해준다.\n\n$ vi ~/.vimrc\n\n\nsyntax on\nfiletype indent plugin on\nset tabstop=4\nset expandtab!\nset softtabstop=4\nset nu\n\nlet g:python_recommended_style=0\n\n\n위의 설정은 필자가 선호하는 vim 설정이다. \n그런데 다소 이해가 되지 않는 부분이 있을 것이다.\n\n파이썬에서는 Tab을 Space로 \n변경해주는 것이 핵심이라고 하면서 \nset expandtab! 설정을 통해서 \n오히려 텝을 스페이스로 바꿔주지 않도록 하고 있다.\n\n필자는 기본적으로 C언어 작업과 파이썬을 병행한다. \n또한 C언어로 코딩할때 텝은 4칸을 선호한다.\n\n따라서 필자가 C언어로 코딩할때는 텝을 그대로 사용 가능하고, \n텝은 공백 4칸으로 설정이 된다.\n\n반면, 파이썬으로 코딩할때는 아래 구문에 의해서 \n텝이 자동으로 스페이스로 변환된다.\n\nlet g:python_recommended_style=0\n\n위의 코드 이전에 설정한 값들이 \nlet g:python_recommended_style=0 설정에 의해서 \noverwrite될 수 있음을 유의한다.\n\n예를들면, set expand tab!과 같은 설정은 \npython 스크립트 편집시에는 전혀 먹히지 않는다는 것이다.\n\npython syntax 파일 다운로드 방법\n\npython syntax 파일은 아래 위치에서 다운로드 받을 수 있다.\n\nhttps://www.vim.org/scripts/script.php?script_id=790\n\npython.vim 파일은 ~/.vim/syntax 경로에 저장하면 된다.\n\n위의 페이지에 접속하는게 번거롭다면 아래 링크에서 다운로드 받으면 된다.\n\npython.vim\n\n아래의 명령으로 한 번에 다운로드가 가능하다.\n\n$ mkdir -p ~/.vim/syntax\n$ wget -O ~/.vim/syntax/syntax.vim https://boyinblue.github.io/004_python/python.vim\n\n\n결론\n\n파이썬은 띄워쓰기에 아주 민감한 언어이다. \n그 이유는 파이썬에서의 씌워쓰기는 문법의 일부이기 때문이다.\n\nvim에서 파이썬 스크립트를 편리하게 편집하기 위한 \n설정 방법에 대해서도 언급하였다.\n"]
Title : 파이썬 명령행 인자 사용 방법
URL : /004_python/003-python-명령행인자.html
Description : 파이썬 스크립트 실행시에 명령행 인자를 추가하는 방법
Content : 명령행 인자가 왜 필요한가?

파이썬을 이용해서 조명을 제어하는 코드를 작성한다고 가정하자.
조명 제어를 위한 아주 필수적인 메쏘드는 2가지이다.

조명 제어를 위한 메쏘드


조명을 켠다.
조명을 끈다.


위의 메쏘드를 실제로 라즈베리파이로 구현하면 아래와 같다.

import RPi.GPIO as GPIO

def light_on():
GPIO.setmode(GPIO.BCM)
GPIO.setup(27, GPIO.OUT)
GPIO.output(27, False) #Low Active

def light_off():
GPIO.setmode(GPIO.BCM)
GPIO.setup(27, GPIO.OUT)
GPIO.output(27, True) #Low Active


해당 스크립트 하나로 어떨때는 조명을 끄고,
어떨때는 조명을 켜도록 하고 싶으면 어떻게 해야 할까?

우선 먼저 어떤 동작을 할지에 대한 내용을
표준입력(사용자 키보드 입력)으로 받아서 처리하는 방법이 있겠다.

표준 입력을 통한 처리

def main():
while True:
cmd = input("cmd : ")
if cmd.lower() == "on":
light_on()
elif cmd.lower() == "off":
light_off()
else:
print("Unknown Command")

if __name__ == '__main__':
main()


위의 스크립트는 input 함수를 통해서
표준입력(키보드)로 받은 문자열로 전등을 켤 수도 있고,
반대로 전등을 끌 수도 있다.

$ sudo python3 light.py
cmd : on
cmd : off


on을 입력하면 전등이 실제로 켜지고,
off를 입력하면 전등이 실제로 꺼진다.

일단 잘 동작하는 것 같지만 한 가지 문제가 있다.
표준 입력 없이는 어떠한 동작도 할 수 없다는 것이다.

만약 위의 파이썬 스크립트를 crontab이나
bash 스크립트에서 호출하고자 한다면
표준 출력을 다시 표준 입력으로 넣어주는 번거로움이 있다.

만약 오전 6시마다 crontab이 전등을 켜도록 하고,
저녁 9시마다 crontab이 전등을 끄게 하려면
아래와 같이 다소 깔끔하지 못한 명령을 입력해야 한다.

$ echo on | sudo python3 light.py


light.py 파일이 표준 입력으로 제어 명령을 받기 때문에
표준 출력으로 "on"을 출력하고, 파이프를 통해서
표준 출력을 다시 sudo python3 light.py의
표준 입력으로 넣어주는 트릭(?)을 쓸 수밖에 없다.

명령행 인자 사용

위와 같이 표준 입력을 통해서 사용자의 입력을 받아서 처리하는 방법도 있겠지만
스크립트 실행 시점에 어떤 동작을 할지를 인자로 넣어주는 방법이 훨씬 깔끔하다.

명령행 인자 내용 확인

import sys

for i in range( 1, len(sys.argv) ):
print("[ARG{}] {}".format(i, sys.argv[i]))


위의 예제는 파이썬 스크립트 실행시에 입력한 인자 목록을
출력하는 간단한 파이썬 스크립트이다.

인자 없이 실행

$ python3 command_line_param.py



작성한 파이썬 스크립트를 실행시에 아무 인자도 넣지 않는다면
위와 같이 아무 인자도 출력되지 않는다.

인자 1개 입력하여 실행

$ python3 command_line_param.py abc
[ARG1] abc


위와 같이 인자 1개를 입력하면 첫 번째 인자로 입력한 문자열이 출력된다.

인자 2개 입력하여 실행

$ python3 command_line_param.py abc def
[ARG1] abc
[ARG2] def


위와 같이 인자 2개를 입력하면 인자로 입력한 문자열이 모두 출력된다.

명령행 인자 예제

이제 조명을 켤 지 끌 지에 대해서 실행시에 알려줄 수 있다.

import sys

if sys.argv[1] == "on":
light_on()
elif sys.argv[1] == "off":
light_off()
else:
print("정의되지 않은 명령입니다.")


위와 같이 첫 번째 인자는 sys.argv[1]에 들어온다.
그 값이 on이면 조명이 켜지게 되고,
그 값이 off이면 조명이 꺼지게 된다.
그 이외의 명령이 들어오면 “정의되지 않은 명령입니다.”가 출력되면서
스크립트가 종료되게 됩니다.

$ python3 light.py on
조명을 켭니다.

$ python3 light.py off
조명을 끕니다.

$ python3 light.py quit
정의되지 않은 명령입니다.


명령행 인자를 통해서 표준입력 없이 다양한 동작들을
수행할 수 있다는 것을 알게 되었다.

명령행 인자로 옵션 받기

위와 같은 조명 제어 예제는 아주 간단했다.
명령행 인자로 들어오는 인자 순서가 정해져 있기 때문이다.

만약, 순서에 정의되지 않은 옵션을 받고 싶다면
아래와 같이 스크립트를 작성해주면 된다.

아래의 스크립트는 실행시에 인자로
GitHub username과 token을 입력받는 실제 스크립트 중 일부이다.

import sys

for i in range( 1, len(sys.argv) ):
if "-user=" in sys.argv[i]:
GITHUB_USER = sys.argv[i][6:]
elif "-token" in sys.argv[i]:
GITHUB_TOKEN = sys.argv[i][7:]
elif "-target_dir=" in sys.argv[i]:
target_dir = sys.argv[i][12:]


만약 GitHub ID의 username이 boyinblue이고, token이 ffffffff라면,
아래와 같이 실행시에 입력하면 된다.

$ python3 git_api.py -user=boyinblue -token=ffffffff


GitHub API 호출에 필요한 username과 token을
스크립트 실행시 호출한 인자에서 가져올 수 있어 편리하다.

결론

이상으로 파이썬 실행시에 입력받은 인자를 처리하는 방법에 대한 설명을
모두 마칩니다.

["명령행 인자가 왜 필요한가?\n\n파이썬을 이용해서 조명을 제어하는 코드를 작성한다고 가정하자. \n조명 제어를 위한 아주 필수적인 메쏘드는 2가지이다.\n\n조명 제어를 위한 메쏘드\n\n\n 조명을 켠다.\n 조명을 끈다.\n\n\n위의 메쏘드를 실제로 라즈베리파이로 구현하면 아래와 같다.\n\nimport RPi.GPIO as GPIO\n\ndef light_on():\n GPIO.setmode(GPIO.BCM)\n GPIO.setup(27, GPIO.OUT)\n GPIO.output(27, False) #Low Active\n\ndef light_off():\n GPIO.setmode(GPIO.BCM)\n GPIO.setup(27, GPIO.OUT)\n GPIO.output(27, True) #Low Active\n\n\n해당 스크립트 하나로 어떨때는 조명을 끄고, \n어떨때는 조명을 켜도록 하고 싶으면 어떻게 해야 할까?\n\n우선 먼저 어떤 동작을 할지에 대한 내용을 \n표준입력(사용자 키보드 입력)으로 받아서 처리하는 방법이 있겠다.\n\n표준 입력을 통한 처리\n\ndef main():\n while True:\n cmd = input(\"cmd : \")\n if cmd.lower() == \"on\":\n light_on()\n elif cmd.lower() == \"off\":\n light_off()\n else:\n print(\"Unknown Command\")\n\nif __name__ == '__main__':\n main()\n\n\n위의 스크립트는 input 함수를 통해서 \n표준입력(키보드)로 받은 문자열로 전등을 켤 수도 있고, \n반대로 전등을 끌 수도 있다.\n\n$ sudo python3 light.py\ncmd : on\ncmd : off\n\n\non을 입력하면 전등이 실제로 켜지고, \noff를 입력하면 전등이 실제로 꺼진다.\n\n일단 잘 동작하는 것 같지만 한 가지 문제가 있다. \n표준 입력 없이는 어떠한 동작도 할 수 없다는 것이다.\n\n만약 위의 파이썬 스크립트를 crontab이나 \nbash 스크립트에서 호출하고자 한다면 \n표준 출력을 다시 표준 입력으로 넣어주는 번거로움이 있다.\n\n만약 오전 6시마다 crontab이 전등을 켜도록 하고, \n저녁 9시마다 crontab이 전등을 끄게 하려면 \n아래와 같이 다소 깔끔하지 못한 명령을 입력해야 한다.\n\n$ echo on | sudo python3 light.py\n\n\nlight.py 파일이 표준 입력으로 제어 명령을 받기 때문에 \n표준 출력으로 \"on\"을 출력하고, 파이프를 통해서 \n표준 출력을 다시 sudo python3 light.py의 \n표준 입력으로 넣어주는 트릭(?)을 쓸 수밖에 없다.\n\n명령행 인자 사용\n\n위와 같이 표준 입력을 통해서 사용자의 입력을 받아서 처리하는 방법도 있겠지만 \n스크립트 실행 시점에 어떤 동작을 할지를 인자로 넣어주는 방법이 훨씬 깔끔하다.\n\n명령행 인자 내용 확인\n\nimport sys\n\nfor i in range( 1, len(sys.argv) ):\n print(\"[ARG{}] {}\".format(i, sys.argv[i]))\n\n\n위의 예제는 파이썬 스크립트 실행시에 입력한 인자 목록을 \n출력하는 간단한 파이썬 스크립트이다.\n\n인자 없이 실행\n\n$ python3 command_line_param.py\n\n\n\n작성한 파이썬 스크립트를 실행시에 아무 인자도 넣지 않는다면 \n위와 같이 아무 인자도 출력되지 않는다.\n\n인자 1개 입력하여 실행\n\n$ python3 command_line_param.py abc\n[ARG1] abc\n\n\n위와 같이 인자 1개를 입력하면 첫 번째 인자로 입력한 문자열이 출력된다.\n\n인자 2개 입력하여 실행\n\n$ python3 command_line_param.py abc def\n[ARG1] abc\n[ARG2] def\n\n\n위와 같이 인자 2개를 입력하면 인자로 입력한 문자열이 모두 출력된다.\n\n명령행 인자 예제\n\n이제 조명을 켤 지 끌 지에 대해서 실행시에 알려줄 수 있다.\n\nimport sys\n\nif sys.argv[1] == \"on\":\n light_on()\nelif sys.argv[1] == \"off\":\n light_off()\nelse:\n print(\"정의되지 않은 명령입니다.\")\n\n\n위와 같이 첫 번째 인자는 sys.argv[1]에 들어온다. \n그 값이 on이면 조명이 켜지게 되고, \n그 값이 off이면 조명이 꺼지게 된다. \n그 이외의 명령이 들어오면 “정의되지 않은 명령입니다.”가 출력되면서 \n스크립트가 종료되게 됩니다.\n\n$ python3 light.py on\n조명을 켭니다.\n\n$ python3 light.py off\n조명을 끕니다.\n\n$ python3 light.py quit\n정의되지 않은 명령입니다.\n\n\n명령행 인자를 통해서 표준입력 없이 다양한 동작들을 \n수행할 수 있다는 것을 알게 되었다.\n\n명령행 인자로 옵션 받기\n\n위와 같은 조명 제어 예제는 아주 간단했다. \n명령행 인자로 들어오는 인자 순서가 정해져 있기 때문이다.\n\n만약, 순서에 정의되지 않은 옵션을 받고 싶다면 \n아래와 같이 스크립트를 작성해주면 된다.\n\n아래의 스크립트는 실행시에 인자로 \nGitHub username과 token을 입력받는 실제 스크립트 중 일부이다.\n\nimport sys\n\nfor i in range( 1, len(sys.argv) ):\n if \"-user=\" in sys.argv[i]:\n GITHUB_USER = sys.argv[i][6:]\n elif \"-token\" in sys.argv[i]:\n GITHUB_TOKEN = sys.argv[i][7:]\n elif \"-target_dir=\" in sys.argv[i]:\n target_dir = sys.argv[i][12:]\n\n\n만약 GitHub ID의 username이 boyinblue이고, token이 ffffffff라면, \n아래와 같이 실행시에 입력하면 된다.\n\n$ python3 git_api.py -user=boyinblue -token=ffffffff\n\n\nGitHub API 호출에 필요한 username과 token을 \n스크립트 실행시 호출한 인자에서 가져올 수 있어 편리하다.\n\n결론\n\n이상으로 파이썬 실행시에 입력받은 인자를 처리하는 방법에 대한 설명을 \n모두 마칩니다.\n\n"]
Title : 우분투 리눅스에 서비스 등록하는 방법
URL : /008_ubuntu/006-ubuntu-register-serivce.html
Description : 우분투 리눅스에 python 스크립트를 서비스로 등록하는 방법
Content : 우분투 리눅스가 시작되자마자 특정 프로그램 또는 스크립트가
수행되도록 하는 방법은 여러가지가 있다.

crontab을 이용해서 주기적으로 실행?

crontab에 등록해서 실행 여부를 확인한 이후에
원하는 프로그램 또는 스크립트가 수행되지 않고 있다면
백그라운드로 실행되도록 하는 방법이 있을 것이다.

서비스 등록 방법

우선 관리자 권한으로 아래 경로에 파일을 생성합니다.

$ vi /etc/systemd/system/my.service


위의 파일에 아래와 같은 형식으로 입력하고 저장합니다.

[Unit]
Description=Raspberry Pi Monitoring Service

[Service]
Type=simple
user=root
ExecStart=python3 service.py
ExecStop=pkill -f 'python3 service.py'
Restart=on-failure
RestartSec=60
WorkingDirectory=/home/boyinblue/project/raspberry/service

[Install]
WantedBy=multi-user.target


서비스 실행, 종료, 재시작 방법

서비스 실행 방법

$ sudo service raspberry_monitor start


서비스 종료 방법

$ sudo service raspberry_monitor stop


서비스 재시작 방법

$ sudo service raspberry_monitor restart


서비스 상태 확인 방법

$ sudo service raspberry_monitor status


주의할 점

서비스가 백그라운드로 자동으로 실행되기 때문에
백그라운드로 실행시킬 필요는 없습니다.

잘못된 예

ExecStart='python3 service.py &'


서비스는 자동으로 백그라운드로 실행되기 때문에
&를 통해서 실행할 필요가 없습니다.

오히려 이렇게 하게 되면 서비스가 제대로 시작되지 못하거나,
서비스가 제대로 시작되었다는 정보를 확인할 수 없습니다.

좋은 예

ExecStart=python3 service.py

["우분투 리눅스가 시작되자마자 특정 프로그램 또는 스크립트가 \n수행되도록 하는 방법은 여러가지가 있다.\n\ncrontab을 이용해서 주기적으로 실행?\n\ncrontab에 등록해서 실행 여부를 확인한 이후에 \n원하는 프로그램 또는 스크립트가 수행되지 않고 있다면 \n백그라운드로 실행되도록 하는 방법이 있을 것이다.\n\n서비스 등록 방법\n\n우선 관리자 권한으로 아래 경로에 파일을 생성합니다.\n\n$ vi /etc/systemd/system/my.service\n\n\n위의 파일에 아래와 같은 형식으로 입력하고 저장합니다.\n\n[Unit]\nDescription=Raspberry Pi Monitoring Service\n\n[Service]\nType=simple\nuser=root\nExecStart=python3 service.py\nExecStop=pkill -f 'python3 service.py'\nRestart=on-failure\nRestartSec=60\nWorkingDirectory=/home/boyinblue/project/raspberry/service\n\n[Install]\nWantedBy=multi-user.target\n\n\n서비스 실행, 종료, 재시작 방법\n\n서비스 실행 방법\n\n$ sudo service raspberry_monitor start\n\n\n서비스 종료 방법\n\n$ sudo service raspberry_monitor stop\n\n\n서비스 재시작 방법\n\n$ sudo service raspberry_monitor restart\n\n\n서비스 상태 확인 방법\n\n$ sudo service raspberry_monitor status\n\n\n주의할 점\n\n서비스가 백그라운드로 자동으로 실행되기 때문에 \n백그라운드로 실행시킬 필요는 없습니다.\n\n잘못된 예\n\nExecStart='python3 service.py &'\n\n\n서비스는 자동으로 백그라운드로 실행되기 때문에 \n&를 통해서 실행할 필요가 없습니다.\n\n오히려 이렇게 하게 되면 서비스가 제대로 시작되지 못하거나, \n서비스가 제대로 시작되었다는 정보를 확인할 수 없습니다.\n\n좋은 예\n\nExecStart=python3 service.py\n\n"]
Title : 파이썬 터틀 그래픽 재미있는 모양 예제
URL : /004_python/003-python-turtle-graphic-example.html
Description : 파이썬 터틀 그래픽을 이용해서 원, 삼각형, 사각형, 입체 모양의 별, 꽃, 바퀴 등의 재미있는 모양을 그려보는 예제를 제공합니다.
Content : 저희 첫째 아들과 파이썬 터틀그래픽으로 재미있는 모양들을 그려보면서
즐거운 시간을 보냈습니다.

터틀 그래픽을 통해서 간단한 그리기 예제들을 제공합니다.

본 페이지에서 다루는 터틀 그래픽 메쏘드




메쏘드
동작




forward()
선분을 그립니다.


left()
왼쪽으로 회전합니다.


right()
오른쪽으로 회전합니다.


speed()
그리기 속도를 조정합니다.


width()
펜의 두께를 조정합니다.


setup()
그리기 화면의 크기를 조정합니다.




가장 기본적인 동작부터 시작해서
하나씩 메쏘드를 추가하면서 설명드리겠습니다.

#1. 사각형 그리기

가장 먼저 사각형 그리기 예제부터 나갑니다.

import turtle

for i in range(0,4):
turtle.forward(100)
turtle.left(90)


수행결과



위의 스크립트를 간략하게 설명하자면 for 구문을 통해서
선분 긋기와 방향 전환을 4번 연속 수행하는 스크립트입니다.

import turtle 구문은 터틀 그래픽을 사용할 수 있게 해줍니다.

for i in range(0,4) 구문을 통해서 4번을 반복합니다.

turtle.forward(100) 구문은 길이 100 픽셀의 선분을 긋습니다.

turtle.left(90) 구문은 왼쪽으로 90도만큼 회전을 합니다.

종합해보면 아래와 같은 동작으로 사각형을 만들어 냅니다.

오른쪽으로 100만큼 선분을 긋고 왼쪽으로 90도 회전합니다.
위쪽으로 100만큼 선분을 긋고 왼쪽으로 90도 회전합니다.
왼쪽으로 100만큼 선분을 긋고 왼쪽으로 90도 회전합니다.
아래쪽으로 100만큼 선분을 긋고 왼쪽으로 90도 회전합니다.


#2. 삼각형 그리기

스크립트를 살짝만 수정하면 이번에는 삼각형을 그릴 수 있습니다.

import turtle
import time

for i in range(0,3):
turtle.forward(100)
turtle.left(120)

time.sleep(3)


위의 같이 회전하는 각도를 90도에서 120도로 늘려주면
정삼각형을 그릴 수 있습니다.

수행 결과는 아래와 같습니다.



모양을 사각형에서 삼각형으로 바꾸는 것 외에도
스크립트를 조금 더 수정하였습니다.
눈치채셨나요?

그리기가 끝나자마자 창이 닫히기 때문에 다 그려진 이후에
약 3초동안의 딜레이를 추가하였습니다.

import time

time.sleep(3)


지연 시간을 주기 위해서는 우선 import time 모듈을 추가해야 합니다.

실제로 지연시간을 주는 함수는 time.sleep(3) 구문입니다.

위의 구문으로 3초 동안의 지연 시간을 줄 수 있습니다.

인자로 실수를 입력하면 1초 이내의 시간동안 지연시키는 것도 가능합니다.

time.sleep(0.1) 구문은 0.1초 동안의 딜레이를 제공합니다.

#3. 별 그리기

다음으로 별을 그리는 방법입니다.

import turtle
import time

def draw_star():
for i in range(0,5):
turtle.forward(100)
turtle.left(144)

time.sleep(5)

if __name__ == '__main__':
draw_star()


수행 결과는 아래와 같습니다.



144도씩 총 5번을 회전해서 별이 완성되었습니다.
총 720도를 회전해서 시작 위치로 돌아왔습니다.

참고로 시작 위치로 돌아오게 하기 위해서는
최소 공배수를 360도의 배수로 맞추면 됩니다.

이번에도 기존에 없는 구문을 조금 더 추가하였습니다.

def draw_star(): 구문을 통해서 별을 그리는 구문을
함수로 작성하였습니다.

또한 if __name__ == '__main__': 구문을 통해서
main으로 실행될 때만 별 모양이 그려지도록 했습니다.
따라서 다른 파이선 스크립트에서 모듈로 import 되었을 때에는
draw_start() 함수를 호출해야만 실행되도록 하였습니다.

지금부터 설명드리는 모양 예제들을 함수 형태로만 제공하겠습니다.

#4. 오른쪽으로 회전하면서 별 그리기

이번에는 반대 방향으로 별을 그려보겠습니다.

def draw_star_reverse():
for i in range(0,5):
turtle.forward(100)
turtle.right(144)


실행 결과는 아래와 같습니다.



turtle.left(144) 구문 대신에
turtle.right(144) 구문을 사용해서
왼쪽이 아닌 오른쪽으로 회전하면서 별을 그리도록 했습니다.

저희 아들이 이건 별이 아니라 여우같다고 하네요.

#5. 입체 모양의 별 그리기

이번에는 각도를 살짝 어긋나게해서 살짝 입체적인 느낌이 들도록
별을 좀 더 예쁘게 그려보겠습니다.

def draw_3d_star():
for i in range(0,10):
turtle.forward(100)
turtle.left(145)


수행 결과



위와 같이 1도씩 틀어지게하고, 선분 개수를 2배로 늘이면 됩니다.

#6. 태양 그리기

이번에는 팬 크기를 좀 더 키워서
왕관 모양이 10개짜리 태양을 그려보겠습니다.

def draw_sun():

turtle.width(3)

for i in range(0,10):
turtle.forward(100)
turtle.left(108)


실행 결과



turtle.width(3) 구문을 통해서 좀 더 두꺼운 펜으로
그림을 그릴 수 있게 되었습니다.

108도와 360도의 최소 공배수는 1080이므로
for 구문으로 10번만 반복하면 됩니다.
또한 태양의 왕관 모양의 개수는 총 10개가 됩니다.

#7. 꽃잎 모양 그리기 (꽃잎 18개)

이번에는 각도를 살짝 조정해서 꽃을 그려보겠습니다.

def draw_sun2():
turtle.width(3)
for i in range(0,18):
turtle.forward(100)
turtle.left(140)


기존의 태양이 108도만큼 회전을 했다면
이번에는 140도 만큼 회전을 하도록 변경하였습니다.

140도와 360도 배수와의 최소 공배수는 2520도 이므로
18번 반복을 해주면 원래 위치로 돌아옵니다.

실행 결과는 아래와 같습니다.



#8. 꽃잎이 36개인 꽃 그리기

실행 결과



실행 결과를 보면 국화랑 비슷한 모양입니다.

#9. 자동차 바퀴 그리기

이번에는 자동차 바퀴를 그려보겠습니다.

def draw_tier():
turtle.speed(0)
for i in range(0,90):
turtle.forward(100)
turtle.left(89)


89도씩 90번을 회전하면 선분으로 타이어를 그릴 수 있습니다.



이번에는 turtle.speed() 메쏘드를 살짝 끼워 넣었습니다.

그 이유는 선분을 무려 90개나 그리기 때문에
Normal Speed로 그리면 너무 오래 걸리기 때문입니다.

turtle.speed() 메소드는 그리기 속도를 변경하는 함수입니다.

넣어주는 인자에 따라서 다른 속도로 그릴 수 있습니다.

turtle.speed() 함수의 매개변수




인자
의미




0
최고 속도


1
속도가 느림



값이 커질수록 점점 빨라짐


10
속도가 빠름




인자를 넣을때 주의할 점입니다.

1에서부터 10까지 갈수록 점점 빨라짐.
0은 최고 속도라는 것에 주의
실수는 입력이 안됨. (ex : 0.5를 입력하면 0이 됨)
10 이상의 값을 입력해도 10이상 빨라지지 않음


#10. 자동차 휠 그리기

이번에는 입체적인 별모양 그리기를 살짝 응용해서
자동차 휠을 그리는 예제를 제공합니다.

def draw_wheel():
turtle.setup(width=400, height=400)
for i in range(0,40):
turtle.forward(100)
turtle.left(145)


수행 결과



결과를 보면, 5각형 모양의 별이 그려지는듯 하더니,
별 모양에서 1도씩 틀어지는 궤적이 남게 됩니다.

이 궤적이 어느정도 중첩되면 결국 휠 모양이 되게 됩니다.

이번 예제에서는 turtle.setup()이라는 새로운 메소드가 등장합니다.

turtle.setup(width=400, height=400) 구문은
터틀 그래픽이 그려질 윈도우의 크기를 변경하는 메소드입니다.

가로 400 픽셀, 세로 400 픽셀 크기로 윈도우 크기가 변경이 됩니다.

결론

이것으로 파이썬 터틀 그래픽을 이용해서 여러가지 모양들을 생성하는
파이썬 스크립트 예제를 살펴보았습니다.

다음 페이지에서는 circle() 메쏘드를 이용해서
좀 더 다양한 모양의 예제들을 제공합니다.
["저희 첫째 아들과 파이썬 터틀그래픽으로 재미있는 모양들을 그려보면서 \n즐거운 시간을 보냈습니다.\n\n터틀 그래픽을 통해서 간단한 그리기 예제들을 제공합니다.\n\n본 페이지에서 다루는 터틀 그래픽 메쏘드\n\n\n \n \n 메쏘드\n 동작\n \n \n \n \n forward()\n 선분을 그립니다.\n \n \n left()\n 왼쪽으로 회전합니다.\n \n \n right()\n 오른쪽으로 회전합니다.\n \n \n speed()\n 그리기 속도를 조정합니다.\n \n \n width()\n 펜의 두께를 조정합니다.\n \n \n setup()\n 그리기 화면의 크기를 조정합니다.\n \n \n\n\n가장 기본적인 동작부터 시작해서 \n하나씩 메쏘드를 추가하면서 설명드리겠습니다.\n\n#1. 사각형 그리기\n\n가장 먼저 사각형 그리기 예제부터 나갑니다.\n\nimport turtle\n\nfor i in range(0,4):\n turtle.forward(100)\n turtle.left(90)\n\n\n수행결과\n\n\n\n위의 스크립트를 간략하게 설명하자면 for 구문을 통해서 \n선분 긋기와 방향 전환을 4번 연속 수행하는 스크립트입니다.\n\nimport turtle 구문은 터틀 그래픽을 사용할 수 있게 해줍니다.\n\nfor i in range(0,4) 구문을 통해서 4번을 반복합니다.\n\nturtle.forward(100) 구문은 길이 100 픽셀의 선분을 긋습니다.\n\nturtle.left(90) 구문은 왼쪽으로 90도만큼 회전을 합니다.\n\n종합해보면 아래와 같은 동작으로 사각형을 만들어 냅니다.\n\n 오른쪽으로 100만큼 선분을 긋고 왼쪽으로 90도 회전합니다.\n 위쪽으로 100만큼 선분을 긋고 왼쪽으로 90도 회전합니다.\n 왼쪽으로 100만큼 선분을 긋고 왼쪽으로 90도 회전합니다.\n 아래쪽으로 100만큼 선분을 긋고 왼쪽으로 90도 회전합니다.\n\n\n#2. 삼각형 그리기\n\n스크립트를 살짝만 수정하면 이번에는 삼각형을 그릴 수 있습니다.\n\nimport turtle\nimport time\n\nfor i in range(0,3):\n turtle.forward(100)\n turtle.left(120)\n\ntime.sleep(3)\n\n\n위의 같이 회전하는 각도를 90도에서 120도로 늘려주면 \n정삼각형을 그릴 수 있습니다.\n\n수행 결과는 아래와 같습니다.\n\n\n\n모양을 사각형에서 삼각형으로 바꾸는 것 외에도 \n스크립트를 조금 더 수정하였습니다. \n눈치채셨나요?\n\n그리기가 끝나자마자 창이 닫히기 때문에 다 그려진 이후에 \n약 3초동안의 딜레이를 추가하였습니다.\n\nimport time\n\ntime.sleep(3)\n\n\n지연 시간을 주기 위해서는 우선 import time 모듈을 추가해야 합니다.\n\n실제로 지연시간을 주는 함수는 time.sleep(3) 구문입니다.\n\n위의 구문으로 3초 동안의 지연 시간을 줄 수 있습니다.\n\n인자로 실수를 입력하면 1초 이내의 시간동안 지연시키는 것도 가능합니다.\n\ntime.sleep(0.1) 구문은 0.1초 동안의 딜레이를 제공합니다.\n\n#3. 별 그리기\n\n다음으로 별을 그리는 방법입니다.\n\nimport turtle\nimport time\n\ndef draw_star():\n for i in range(0,5):\n turtle.forward(100)\n turtle.left(144)\n\n time.sleep(5)\n\nif __name__ == '__main__':\n draw_star()\n\n\n수행 결과는 아래와 같습니다.\n\n\n\n144도씩 총 5번을 회전해서 별이 완성되었습니다. \n총 720도를 회전해서 시작 위치로 돌아왔습니다.\n\n참고로 시작 위치로 돌아오게 하기 위해서는 \n최소 공배수를 360도의 배수로 맞추면 됩니다.\n\n이번에도 기존에 없는 구문을 조금 더 추가하였습니다.\n\ndef draw_star(): 구문을 통해서 별을 그리는 구문을 \n함수로 작성하였습니다.\n\n또한 if __name__ == '__main__': 구문을 통해서 \nmain으로 실행될 때만 별 모양이 그려지도록 했습니다. \n따라서 다른 파이선 스크립트에서 모듈로 import 되었을 때에는 \ndraw_start() 함수를 호출해야만 실행되도록 하였습니다.\n\n지금부터 설명드리는 모양 예제들을 함수 형태로만 제공하겠습니다.\n\n#4. 오른쪽으로 회전하면서 별 그리기\n\n이번에는 반대 방향으로 별을 그려보겠습니다.\n\ndef draw_star_reverse():\n for i in range(0,5):\n turtle.forward(100)\n turtle.right(144)\n\n\n실행 결과는 아래와 같습니다.\n\n\n\nturtle.left(144) 구문 대신에 \nturtle.right(144) 구문을 사용해서 \n왼쪽이 아닌 오른쪽으로 회전하면서 별을 그리도록 했습니다.\n\n저희 아들이 이건 별이 아니라 여우같다고 하네요.\n\n#5. 입체 모양의 별 그리기\n\n이번에는 각도를 살짝 어긋나게해서 살짝 입체적인 느낌이 들도록 \n별을 좀 더 예쁘게 그려보겠습니다.\n\ndef draw_3d_star():\n for i in range(0,10):\n turtle.forward(100)\n turtle.left(145)\n\n\n수행 결과\n\n\n\n위와 같이 1도씩 틀어지게하고, 선분 개수를 2배로 늘이면 됩니다.\n\n#6. 태양 그리기\n\n이번에는 팬 크기를 좀 더 키워서 \n왕관 모양이 10개짜리 태양을 그려보겠습니다.\n\ndef draw_sun():\n\n turtle.width(3)\n\n for i in range(0,10):\n turtle.forward(100)\n turtle.left(108)\n\n\n실행 결과\n\n\n\nturtle.width(3) 구문을 통해서 좀 더 두꺼운 펜으로 \n그림을 그릴 수 있게 되었습니다.\n\n108도와 360도의 최소 공배수는 1080이므로 \nfor 구문으로 10번만 반복하면 됩니다. \n또한 태양의 왕관 모양의 개수는 총 10개가 됩니다.\n\n#7. 꽃잎 모양 그리기 (꽃잎 18개)\n\n이번에는 각도를 살짝 조정해서 꽃을 그려보겠습니다.\n\ndef draw_sun2():\n turtle.width(3)\n for i in range(0,18):\n turtle.forward(100)\n turtle.left(140)\n\n\n기존의 태양이 108도만큼 회전을 했다면 \n이번에는 140도 만큼 회전을 하도록 변경하였습니다.\n\n140도와 360도 배수와의 최소 공배수는 2520도 이므로 \n18번 반복을 해주면 원래 위치로 돌아옵니다.\n\n실행 결과는 아래와 같습니다.\n\n\n\n#8. 꽃잎이 36개인 꽃 그리기\n\n실행 결과\n\n\n\n실행 결과를 보면 국화랑 비슷한 모양입니다.\n\n#9. 자동차 바퀴 그리기\n\n이번에는 자동차 바퀴를 그려보겠습니다.\n\ndef draw_tier():\n turtle.speed(0)\n for i in range(0,90):\n turtle.forward(100)\n turtle.left(89)\n\n\n89도씩 90번을 회전하면 선분으로 타이어를 그릴 수 있습니다.\n\n\n\n이번에는 turtle.speed() 메쏘드를 살짝 끼워 넣었습니다.\n\n그 이유는 선분을 무려 90개나 그리기 때문에 \nNormal Speed로 그리면 너무 오래 걸리기 때문입니다.\n\nturtle.speed() 메소드는 그리기 속도를 변경하는 함수입니다.\n\n넣어주는 인자에 따라서 다른 속도로 그릴 수 있습니다.\n\nturtle.speed() 함수의 매개변수\n\n\n \n \n 인자\n 의미\n \n \n \n \n 0\n 최고 속도\n \n \n 1\n 속도가 느림\n \n \n …\n 값이 커질수록 점점 빨라짐\n \n \n 10\n 속도가 빠름\n \n \n\n\n인자를 넣을때 주의할 점입니다.\n\n 1에서부터 10까지 갈수록 점점 빨라짐.\n 0은 최고 속도라는 것에 주의\n 실수는 입력이 안됨. (ex : 0.5를 입력하면 0이 됨)\n 10 이상의 값을 입력해도 10이상 빨라지지 않음\n\n\n#10. 자동차 휠 그리기\n\n이번에는 입체적인 별모양 그리기를 살짝 응용해서 \n자동차 휠을 그리는 예제를 제공합니다.\n\ndef draw_wheel():\n turtle.setup(width=400, height=400)\n for i in range(0,40):\n turtle.forward(100)\n turtle.left(145)\n\n\n수행 결과\n\n\n\n결과를 보면, 5각형 모양의 별이 그려지는듯 하더니, \n별 모양에서 1도씩 틀어지는 궤적이 남게 됩니다.\n\n이 궤적이 어느정도 중첩되면 결국 휠 모양이 되게 됩니다.\n\n이번 예제에서는 turtle.setup()이라는 새로운 메소드가 등장합니다.\n\nturtle.setup(width=400, height=400) 구문은 \n터틀 그래픽이 그려질 윈도우의 크기를 변경하는 메소드입니다.\n\n가로 400 픽셀, 세로 400 픽셀 크기로 윈도우 크기가 변경이 됩니다.\n\n결론\n\n이것으로 파이썬 터틀 그래픽을 이용해서 여러가지 모양들을 생성하는 \n파이썬 스크립트 예제를 살펴보았습니다.\n\n다음 페이지에서는 circle() 메쏘드를 이용해서 \n좀 더 다양한 모양의 예제들을 제공합니다.\n"]
Title : GitHub Pages deploy 시에 400 에러나 502 에러가 발생할 경우 조치 방법
URL : /002_github_blog/013-github-pages-deploy-error-400-502.html
Description : GitHub Pages로 새로운 변경점을 반영하려고 할 때 400 에러나 502 에러가 발생할 경우 조치하는 방법입니다.
Content : 어젯밤에 갑자기 GitHub Pages로 업데이트하는 모든 commit에 대해서 deploy가 되지 않는 문제가 발생했습니다.

아시다시피, GitHub Pages는 레포지토리에 파일을 업로드하거나 수정하면,
자동으로 build 및 deploy 과정이 진행됩니다.

여러가지 시도들을 해봤었고, GitHub Pages 서비스 자체의 문제인 것으로 추정됩니다.

문제의 현상

개발자는 크든 작든 수많은 문제점들을 만나게 됩니다.
가장 먼저 해야할 것들은 문제의 현상을 잘 살펴보고,
여러가지 시도들을 하면서 결국에는 문제를 해결하게 됩니다.



제가 목격한 문제의 현상은 아래와 같습니다.


GitHub Pages로 업데이트하는 모든 commit에 대한 deploy 작업이 실패함.
기존에는 빌드와 디플로이를 합친 시간이 1분 내외로 소요되었으나, 문제의 상황에서는 10분에서 30분까지 소요되다가 결국에는 실패함.
아래와 같은 실패 에러들을 deploy 로그에서 볼 수 있음.

Error: Timeout reached, aborting!
Error: Request failed with status code 502
Error: Request failed with status code 400


마지막에 deploy된 웹페이지는 제대로 서비스되고 있음.


시도해본 것들

문제를 해결하거나 원인이 될 만한 것들을 살펴보기 위해서 시도한 것들입니다.

가장 먼저, 제가 업로드한 변경점이 deploy 에러를 유발했을 수 있기 때문에,
기존에 잘 deploy 되던 버전으로 revert 시켜서 확인해 보기도 했고,
다른 계정으로 생성한 GitHub Pages를 deploy 시켜보기도 했습니다.

아래의 3가지 시도 모두 실패했습니다.


GitHub Pages에 업데이트한 변경점을 원복(revert) 시켜봄

예전에 build 및 deploy에 문제 없던 버전에서도 deploy 에러가 발생함.


main branch가 아닌 별도의 branch를 생성해서 GitHub Pages를 연결해 봄

여전히 deploy 에러가 발생함.


다른 계정의 GitHub Pagee를 deploy 시켜봄.

다른 계정의 GitHub Pages에서도 deploy 에러가 발생함.




의외의 해결 방법

이 문제는 GitHub Pages 서비스 자체에 문제가 있다고 생각하고,
잊어버리고 기다리기로 했습니다.

마지막으로 업로드한 페이지는 정상적으로 서비스되고 있기 때문에,
추가로 제가 작업한 내용들이 긴급하게 웹서버에 deploy 될 필요는 없었기 때문입니다.

아무리 GitHub Pages 서비스가 무료라고 하더라도,
여러 계정에서 deploy 에러가 발생한다면
GitHub Pgaes 서비스를 제공하는 측에는 상당히 부담스러운 문제이기 때문입니다.

어젯밤에 발생한 문제를 깔끔하게 잊어버리고 잠을 청했습니다.
오늘 아침 일찍 일어나서 다시 deploy 시켜봤더니 정상적으로 수행됩니다.

결론

GitHub Pages deploy에러가 발생했다면 변경점이 deploy 에러를 유발한 것은 아닌지 살펴봅니다.

만약, 이전에 잘 deploy 되던 버전으로 revert 했음에도 불구하고
지속적인 에러가 발생한다면 GitHub Pages 자체의 문제일 수 있으므로
복구 될 때까지 기다려보시기 바랍니다.

참고할 만한 페이지

만약 deploy 에러가 아니라 build 에러라면 아래의 페이지를 참조하세요.

GitHub Pages 빌드 에러 조치 방법

이상입니다.
["어젯밤에 갑자기 GitHub Pages로 업데이트하는 모든 commit에 대해서 deploy가 되지 않는 문제가 발생했습니다.\n\n아시다시피, GitHub Pages는 레포지토리에 파일을 업로드하거나 수정하면, \n자동으로 build 및 deploy 과정이 진행됩니다.\n\n여러가지 시도들을 해봤었고, GitHub Pages 서비스 자체의 문제인 것으로 추정됩니다.\n\n문제의 현상\n\n개발자는 크든 작든 수많은 문제점들을 만나게 됩니다. \n가장 먼저 해야할 것들은 문제의 현상을 잘 살펴보고, \n여러가지 시도들을 하면서 결국에는 문제를 해결하게 됩니다.\n\n\n\n제가 목격한 문제의 현상은 아래와 같습니다.\n\n\n GitHub Pages로 업데이트하는 모든 commit에 대한 deploy 작업이 실패함.\n 기존에는 빌드와 디플로이를 합친 시간이 1분 내외로 소요되었으나, 문제의 상황에서는 10분에서 30분까지 소요되다가 결국에는 실패함.\n 아래와 같은 실패 에러들을 deploy 로그에서 볼 수 있음.\n \n Error: Timeout reached, aborting!\n Error: Request failed with status code 502\n Error: Request failed with status code 400\n \n \n 마지막에 deploy된 웹페이지는 제대로 서비스되고 있음.\n\n\n시도해본 것들\n\n문제를 해결하거나 원인이 될 만한 것들을 살펴보기 위해서 시도한 것들입니다.\n\n가장 먼저, 제가 업로드한 변경점이 deploy 에러를 유발했을 수 있기 때문에, \n기존에 잘 deploy 되던 버전으로 revert 시켜서 확인해 보기도 했고, \n다른 계정으로 생성한 GitHub Pages를 deploy 시켜보기도 했습니다.\n\n아래의 3가지 시도 모두 실패했습니다.\n\n\n GitHub Pages에 업데이트한 변경점을 원복(revert) 시켜봄\n \n 예전에 build 및 deploy에 문제 없던 버전에서도 deploy 에러가 발생함.\n \n \n main branch가 아닌 별도의 branch를 생성해서 GitHub Pages를 연결해 봄\n \n 여전히 deploy 에러가 발생함.\n \n \n 다른 계정의 GitHub Pagee를 deploy 시켜봄.\n \n 다른 계정의 GitHub Pages에서도 deploy 에러가 발생함.\n \n \n\n\n의외의 해결 방법\n\n이 문제는 GitHub Pages 서비스 자체에 문제가 있다고 생각하고, \n잊어버리고 기다리기로 했습니다.\n\n마지막으로 업로드한 페이지는 정상적으로 서비스되고 있기 때문에, \n추가로 제가 작업한 내용들이 긴급하게 웹서버에 deploy 될 필요는 없었기 때문입니다.\n\n아무리 GitHub Pages 서비스가 무료라고 하더라도, \n여러 계정에서 deploy 에러가 발생한다면 \nGitHub Pgaes 서비스를 제공하는 측에는 상당히 부담스러운 문제이기 때문입니다.\n\n어젯밤에 발생한 문제를 깔끔하게 잊어버리고 잠을 청했습니다. \n오늘 아침 일찍 일어나서 다시 deploy 시켜봤더니 정상적으로 수행됩니다.\n\n결론\n\nGitHub Pages deploy에러가 발생했다면 변경점이 deploy 에러를 유발한 것은 아닌지 살펴봅니다.\n\n만약, 이전에 잘 deploy 되던 버전으로 revert 했음에도 불구하고 \n지속적인 에러가 발생한다면 GitHub Pages 자체의 문제일 수 있으므로 \n복구 될 때까지 기다려보시기 바랍니다.\n\n참고할 만한 페이지\n\n만약 deploy 에러가 아니라 build 에러라면 아래의 페이지를 참조하세요.\n\nGitHub Pages 빌드 에러 조치 방법\n\n이상입니다.\n"]
Title : GitHub Pages에서 css 파일 위치
URL : /002_github_blog/012-github-pages-css-file-path.html
Description : GitHub Pages에서 css를 변경하고자 할 때 편집해야하는 css 파일 위치에 대해서 설명합니다.
Content : GitHub Pages를 개설한지도 3주 가까이 되어가는 것 같습니다.
어떠한 배경 지식도 없이 GitHub Pages를 이용하면
무료로 웹서버를 운영할 수 있다는 메리트 하나만으로 시작했습니다.

구글 사이트 소유 확인, 구글 서치 콘솔 등록, 구글 애널리틱스 등록,
사이트맵 작성, robots.txt 작성 등 해야할 작업도 많았고,
배우고 익혀야 할 것들도 많았습니다.

이 과정들을 최대한 잘 기록해두려고 노력했고, 실제로 그렇게 했습니다.
오늘은 css 파일의 위치에 대해서 설명하고자 합니다.

GitHub Pages의 CSS 파일 찾아가는 과정

GitHub Pages를 운영하시는 분들이라면 거의 테마를 사용하실 것입니다.
저 역시도 jekyll-theme-slate를 사용하고 있습니다.

처음 GitHub Pages를 시작하면, 레포지토리에 어떠한 파일도 존재하지 않습니다.

테마를 설정하면 \_config.yml 파일만 있고 그 외에는 어떠한 파일도 업지요.
그럼에도 불구하고 실제로 웹페이지에 접속해보면 웹 페이지가 뜨는게 신기할 따름입니다.

GitHub Pages에는 레포지토리에 있는 것 그 이상의 미지의 무언가가 존재합니다.

레포지토리에 있는 내용 +@를 이용하여 웹페이지를 만들어 냅니다.

그 +@ 중의 하나가 바로 jekyll-theme 입니다.
사용자가 테마 설정을 명시적으로 변경하지 않는 한 기본 테마를 사용하게 됩니다.

보통의 경우는 테마 파일 전체를 가져오곤 합니다.
혹은 기존의 테마 레포지토리를 fork해서 가져오는 것도
하나의 방법이라고 할 수 있겠습니다.

첫번째, 소스 보기

GitHub Pages의 구조를 파악하는데 시발점이 되는 것이 바로 소스 보기입니다.
웹 브라우저로 웹 페이지에 접속한 이후에 페이지 소스 보기를 수행합니다.

<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset='utf-8'>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,maximum-scale=2">
<link rel="stylesheet" type="text/css" media="screen" href="/assets/css/style.css?v=3f29457c4cd54348a5f421c89bdcaa7095ed0039">


페이지 소스 보기를 하시면 위와 같이 /assets/css/style.css 파일에 스타일이 정의되어 있는 것을 확인하실 수 있습니다.

두 번째, assets/css/style.css 파일 열어보기

그렇다면 실제로 assets/css/style.css 파일을 열어보겠습니다.
허무하게 해당 파일에는 단 한 줄만 존재합니다.

@import "jekyll-theme-slate";


위의 파일을 테마에 따라서 다를 수 있다는 점 유의하시기 바랍니다.

세 번째, _sass 디렉토리 뒤져보기

그렇다면 jekyll-theme-slate라는 파일은 어디에 존재하는 것일까요?
결론부터 말씀드리자면, _sass 디렉토리 내부에 있습니다.

네 번째, jekyll-theme-slate 파일 편집하기

이제 드디어 jekyll-theme-slate 파일을 찾아냈습니다.
입맛에 맞는대로 조금 수정하시면 되겠습니다.

저 같은 경우는 헤더가 너무 크게 느껴져서
헤더의 패딩을 좀 조정했더니 훨씬 보기 좋더군요.

그런데 이게 전부가 아닙니다.
jekyll-theme-slate 파일은 다시 “rogue-github”라는 파일을 import 하기 때문입니다.

즉, GitHub Pages에서 스타일 정의를 수정하고 싶으시다면
아래 2가지 경로의 파일을 수정하시면 되겠습니다.
물론, 사용하시는 테마에 따라서 다소 다를 수 있습니다.


/_sass/jekyll-theme-slate.scss 파일
/_sass/rouge-github.scss 파일


결론

본 페이지에서는 GitHub Pages에서 스타일을 수정하고 싶을 때
어떤 파일을 편집해야 하는지에 대해서 설명드렸습니다.
["GitHub Pages를 개설한지도 3주 가까이 되어가는 것 같습니다. \n어떠한 배경 지식도 없이 GitHub Pages를 이용하면 \n무료로 웹서버를 운영할 수 있다는 메리트 하나만으로 시작했습니다.\n\n구글 사이트 소유 확인, 구글 서치 콘솔 등록, 구글 애널리틱스 등록, \n사이트맵 작성, robots.txt 작성 등 해야할 작업도 많았고, \n배우고 익혀야 할 것들도 많았습니다.\n\n이 과정들을 최대한 잘 기록해두려고 노력했고, 실제로 그렇게 했습니다. \n오늘은 css 파일의 위치에 대해서 설명하고자 합니다.\n\nGitHub Pages의 CSS 파일 찾아가는 과정\n\nGitHub Pages를 운영하시는 분들이라면 거의 테마를 사용하실 것입니다. \n저 역시도 jekyll-theme-slate를 사용하고 있습니다.\n\n처음 GitHub Pages를 시작하면, 레포지토리에 어떠한 파일도 존재하지 않습니다.\n\n테마를 설정하면 \\_config.yml 파일만 있고 그 외에는 어떠한 파일도 업지요. \n그럼에도 불구하고 실제로 웹페이지에 접속해보면 웹 페이지가 뜨는게 신기할 따름입니다.\n\nGitHub Pages에는 레포지토리에 있는 것 그 이상의 미지의 무언가가 존재합니다.\n\n레포지토리에 있는 내용 +@를 이용하여 웹페이지를 만들어 냅니다.\n\n그 +@ 중의 하나가 바로 jekyll-theme 입니다. \n사용자가 테마 설정을 명시적으로 변경하지 않는 한 기본 테마를 사용하게 됩니다.\n\n보통의 경우는 테마 파일 전체를 가져오곤 합니다. \n혹은 기존의 테마 레포지토리를 fork해서 가져오는 것도 \n하나의 방법이라고 할 수 있겠습니다.\n\n첫번째, 소스 보기\n\nGitHub Pages의 구조를 파악하는데 시발점이 되는 것이 바로 소스 보기입니다. \n웹 브라우저로 웹 페이지에 접속한 이후에 페이지 소스 보기를 수행합니다.\n\n<!DOCTYPE html>\n<html lang=\"en-US\">\n <head>\n <meta charset='utf-8'>\n <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n <meta name=\"viewport\" content=\"width=device-width,maximum-scale=2\">\n <link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\"/assets/css/style.css?v=3f29457c4cd54348a5f421c89bdcaa7095ed0039\">\n\n\n페이지 소스 보기를 하시면 위와 같이 /assets/css/style.css 파일에 스타일이 정의되어 있는 것을 확인하실 수 있습니다.\n\n두 번째, assets/css/style.css 파일 열어보기\n\n그렇다면 실제로 assets/css/style.css 파일을 열어보겠습니다. \n허무하게 해당 파일에는 단 한 줄만 존재합니다.\n\n@import \"jekyll-theme-slate\";\n\n\n위의 파일을 테마에 따라서 다를 수 있다는 점 유의하시기 바랍니다.\n\n세 번째, _sass 디렉토리 뒤져보기\n\n그렇다면 jekyll-theme-slate라는 파일은 어디에 존재하는 것일까요? \n결론부터 말씀드리자면, _sass 디렉토리 내부에 있습니다.\n\n네 번째, jekyll-theme-slate 파일 편집하기\n\n이제 드디어 jekyll-theme-slate 파일을 찾아냈습니다. \n입맛에 맞는대로 조금 수정하시면 되겠습니다.\n\n저 같은 경우는 헤더가 너무 크게 느껴져서 \n헤더의 패딩을 좀 조정했더니 훨씬 보기 좋더군요.\n\n그런데 이게 전부가 아닙니다. \njekyll-theme-slate 파일은 다시 “rogue-github”라는 파일을 import 하기 때문입니다.\n\n즉, GitHub Pages에서 스타일 정의를 수정하고 싶으시다면 \n아래 2가지 경로의 파일을 수정하시면 되겠습니다. \n물론, 사용하시는 테마에 따라서 다소 다를 수 있습니다.\n\n\n /_sass/jekyll-theme-slate.scss 파일\n /_sass/rouge-github.scss 파일\n\n\n결론\n\n본 페이지에서는 GitHub Pages에서 스타일을 수정하고 싶을 때 \n어떤 파일을 편집해야 하는지에 대해서 설명드렸습니다.\n"]
Title : 업비트 API 호출시에 Too many API requests. 문제 해결 방법 3가지
URL : /009_upbit/UPbit-Too-many-API-requests.html
Description : 업비트 API 호출시에 Too many API requests. 문제 발생시에 해결 방법에 대해서 설명합니다.
Content : 이 페이지를 검색해서 열람하시는 분들이라면
API와 업비트의 Open API에 대해서 익숙하신 분들이시겠지요.

저는 매일 오전 9시 5분에 업비트 Open API를 이용해서
일간 캔들 정보를 긁어와서 간단한 통계 자료를 만들고 있습니다.

잘 동작하던 파이선 스크립트가 어제부터 아래와 같은 에러가
발생하기 시작하더군요.

Too many API requests.


다행히 제가 작성한 스크립트의 문제는 아니었습니다.
모든 마켓의 캔들 정보를 연속으로 요청하다보니
당연히 발생할 수 밖에 없는 상황입니다.

사실 수많은 API가 Query(쿼리)의 개수나 순간 처리량 등을 제한하고 있습니다.
꼭 API가 아니더라도 지메일(gmail) 같은 서비스 역시도 과도한 부하가 걸리지 않도록 쿼터제를 운영하고 있습니다.

업비트 API의 요청 수 제한

업비트의 API 페이지에 가보면 API로 처리 가능한 요청 수 제한을 확인할 수 있습니다.

업비트 API

해당 페이지를 살펴보면 EXCHANGE API와 QUOTATION API에 대한
요청수를 제한해 두었습니다.

![업비트 API 요청 수]

초당 요청수와 분당 요청수가 제한되어 있는데,
이 중에서 하나라도 초과하면 제대로된 응답을 받을 수 없습니다.

다행히 과도한 쿼리에 대한 패널티는 없고,
시간이 지나면 자동으로 해제가 됩니다.

업비트 요청 수 제한 회피 방법 (첫번째)

우선 가장 먼저 단순하고 무식한 방법은
쿼리와 쿼리 사이에 적당한 딜레이를 주는 것입니다.

단순 조회용 API는 초당 10회까지 사용할 수 있으므로,
쿼리마다 100ms의 딜레이를 주게되면 안정적으로 API를 처리할 수 있습니다.

# 마켓 목록을 market_code.json 파일에서 가져옴
with open("tmp/market_code.json") as json_file:
json_data = json.load(json_file)
for market_json_data in json_data:
print(market_json_data)
load_data_from_upbit(yesterday_date, market_json_data['market'])
time.sleep(0.1)


기존 스크립트에는 딜레이 전혀 없이 처리를 했었는데,
이번에는 time.sleep(0.1)을 넣어줬습니다.

위와 같이 수행했더니 에러 없이 잘 처리가 되었습니다.
하지만 이렇게 처리를 했을 경우에 의도하지 않은 문제가 발생할 수 있습니다.

업비트 요청 수 제한 회피 방법 (두번째)

위와 같은 방법은 업비트에서 요청 수 처리 제한 정책이 바뀌면
적당히 넣어준 딜레이 값을 다시 변경해줘야 되는 단점이 있습니다.

예를들어서, 1분당 60개까지 요청할 수 있도록 되어 있었는데
어느 순간 업비트에서 1분당 30개만 처리할 수 있도록 정책을 바꾼다면
우리는 다시 또 “Too many API requests.” 메시지를 맛보게 될 것이고
적당히 딜레이를 더 넣어주는 작업을 또 해줘야 하기 때문입니다.

손과 발이 편하자고 자동화를 하는데 조금이라도 수고로움을 줄여야 하겠지요.
try - exception 구문을 사용해서 10번까지 재시도를 하도록 해보겠습니다.

# 마켓 목록을 market_code.json 파일에서 가져옴
from json.decoder import JSONDecodeError

with open("tmp/market_code.json") as json_file:
json_data = json.load(json_file)
for market_json_data in json_data:
print(market_json_data)
for trycnt in range(10):
try:
result = load_data_from_upbit(yesterday_date, market_json_data['market'])
if result:
break
except JSONDecodeError as e:
print("JSODecodeError retry", trycnt)
time.sleep(1)
pass
except Exception as e:
raise e


JSONDecodeError를 처리하기 위해서는
json.decoder를 import 시켜야 합니다.

코드를 위와 같이 수정하면 요청 수 제한에 걸리기 전까지
최대한 빠르게 API 호출이 처리됩니다.

그러다가 요청 수 제한에 걸리게 되면 리턴되는 형식이 JSON이 아니라서
JSONDecodeError가 발생하게 됩니다.

이 때는 1초동안 쉬었다가 다시 retry를 하게 됩니다.

업비트 요청 수 제한 회피 방법 (두번째)

마지막 3번째 방법을 웹소켓을 이용하는 방식입니다.

해당 내용은 업비트 페이지 링크로 대신합니다.

업비트 웹소켓 관련 페이지

결론

업비트 API 요청시에 “Too many API requests” 응답을 회피하는 방법에 대해서 알아보았습니다.
["이 페이지를 검색해서 열람하시는 분들이라면 \nAPI와 업비트의 Open API에 대해서 익숙하신 분들이시겠지요.\n\n저는 매일 오전 9시 5분에 업비트 Open API를 이용해서 \n일간 캔들 정보를 긁어와서 간단한 통계 자료를 만들고 있습니다.\n\n잘 동작하던 파이선 스크립트가 어제부터 아래와 같은 에러가 \n발생하기 시작하더군요.\n\nToo many API requests.\n\n\n다행히 제가 작성한 스크립트의 문제는 아니었습니다. \n모든 마켓의 캔들 정보를 연속으로 요청하다보니 \n당연히 발생할 수 밖에 없는 상황입니다.\n\n사실 수많은 API가 Query(쿼리)의 개수나 순간 처리량 등을 제한하고 있습니다. \n꼭 API가 아니더라도 지메일(gmail) 같은 서비스 역시도 과도한 부하가 걸리지 않도록 쿼터제를 운영하고 있습니다.\n\n업비트 API의 요청 수 제한\n\n업비트의 API 페이지에 가보면 API로 처리 가능한 요청 수 제한을 확인할 수 있습니다.\n\n업비트 API\n\n해당 페이지를 살펴보면 EXCHANGE API와 QUOTATION API에 대한 \n요청수를 제한해 두었습니다.\n\n![업비트 API 요청 수]\n\n초당 요청수와 분당 요청수가 제한되어 있는데, \n이 중에서 하나라도 초과하면 제대로된 응답을 받을 수 없습니다.\n\n다행히 과도한 쿼리에 대한 패널티는 없고, \n시간이 지나면 자동으로 해제가 됩니다.\n\n업비트 요청 수 제한 회피 방법 (첫번째)\n\n우선 가장 먼저 단순하고 무식한 방법은 \n쿼리와 쿼리 사이에 적당한 딜레이를 주는 것입니다.\n\n단순 조회용 API는 초당 10회까지 사용할 수 있으므로, \n쿼리마다 100ms의 딜레이를 주게되면 안정적으로 API를 처리할 수 있습니다.\n\n# 마켓 목록을 market_code.json 파일에서 가져옴\nwith open(\"tmp/market_code.json\") as json_file:\n json_data = json.load(json_file)\n for market_json_data in json_data:\n print(market_json_data)\n load_data_from_upbit(yesterday_date, market_json_data['market'])\n time.sleep(0.1)\n\n\n기존 스크립트에는 딜레이 전혀 없이 처리를 했었는데, \n이번에는 time.sleep(0.1)을 넣어줬습니다.\n\n위와 같이 수행했더니 에러 없이 잘 처리가 되었습니다. \n하지만 이렇게 처리를 했을 경우에 의도하지 않은 문제가 발생할 수 있습니다.\n\n업비트 요청 수 제한 회피 방법 (두번째)\n\n위와 같은 방법은 업비트에서 요청 수 처리 제한 정책이 바뀌면 \n적당히 넣어준 딜레이 값을 다시 변경해줘야 되는 단점이 있습니다.\n\n예를들어서, 1분당 60개까지 요청할 수 있도록 되어 있었는데 \n어느 순간 업비트에서 1분당 30개만 처리할 수 있도록 정책을 바꾼다면 \n우리는 다시 또 “Too many API requests.” 메시지를 맛보게 될 것이고 \n적당히 딜레이를 더 넣어주는 작업을 또 해줘야 하기 때문입니다.\n\n손과 발이 편하자고 자동화를 하는데 조금이라도 수고로움을 줄여야 하겠지요. \ntry - exception 구문을 사용해서 10번까지 재시도를 하도록 해보겠습니다.\n\n# 마켓 목록을 market_code.json 파일에서 가져옴\nfrom json.decoder import JSONDecodeError\n\nwith open(\"tmp/market_code.json\") as json_file:\n json_data = json.load(json_file)\n for market_json_data in json_data:\n print(market_json_data)\n for trycnt in range(10):\n try:\n result = load_data_from_upbit(yesterday_date, market_json_data['market'])\n if result:\n break\n except JSONDecodeError as e:\n print(\"JSODecodeError retry\", trycnt)\n time.sleep(1)\n pass\n except Exception as e:\n raise e\n\n\nJSONDecodeError를 처리하기 위해서는 \njson.decoder를 import 시켜야 합니다.\n\n코드를 위와 같이 수정하면 요청 수 제한에 걸리기 전까지 \n최대한 빠르게 API 호출이 처리됩니다.\n\n그러다가 요청 수 제한에 걸리게 되면 리턴되는 형식이 JSON이 아니라서 \nJSONDecodeError가 발생하게 됩니다.\n\n이 때는 1초동안 쉬었다가 다시 retry를 하게 됩니다.\n\n업비트 요청 수 제한 회피 방법 (두번째)\n\n마지막 3번째 방법을 웹소켓을 이용하는 방식입니다.\n\n해당 내용은 업비트 페이지 링크로 대신합니다.\n\n업비트 웹소켓 관련 페이지\n\n결론\n\n업비트 API 요청시에 “Too many API requests” 응답을 회피하는 방법에 대해서 알아보았습니다.\n"]
Title : 업비트 API를 이용하여 일단위 캔들 조회 방법
URL : /009_upbit/UPbit-API-daily-candle-query.html
Description : 업비트에서 제공하는 Open API를 통해서 일단위 캔들을 조회하는 방법 설명
Content : 기존 증권사의 API에 비해서 UPbit의 Open API는 아주 편리하게 되어 있습니다.
캔들 조회는 토큰이 없어도 가능할 뿐만 아니라,
JavaScript, Python, Ruby, Java 등 다양한 프로그래밍 언어를 이용해서 응용프로그램을 작성할 수 있도록 다양한 예제가 제공됩니다.

본 페이지에서는 업비트 API 중에서도 가장 기본적인 기능인 캔들 조회 기능을 간단하게 구현해보고자 합니다.

본 페이지 작성 환경

이 페이지는 아래 환경을 기준으로 작성되었음을 미리 알려드립니다.




OS
프로그래밍 언어
비고




Ubuntu Linux
Python, Curl
 




업비트 Open API 관련 문서

업비트 Open API 관련 문서는 개발자 센터에서 열람하실 수 있습니다.
업비트 Open API 개발자 센터

서두에서도 설명드린 것처럼 다양한 언어로 레퍼런스 코드를 제공하기 때문에
복사해서 붙여넣기로도 큰 어려움 없이 프로그램을 작성하실 수 있습니다.

curl 명령을 통한 시세 조회 (curl 명령)

우선 curl 명령을 통해서 캔들 정보를 받아와보겠습니다.
API를 통한 간단한 조회는 웹브라우저나 curl 명령으로도 충분히 수행 가능합니다.
코드를 작성하거나 그런게 아니므로 처음부터 겁먹을 필요는 없습니다.

curl --request GET \
--url 'https://api.upbit.com/v1/candles/days?count=1' \
--header 'Accept: application/json'


위의 내용을 잘 살펴보면 일 단위(days)의 캔들(candles)들을 조회하는 명령이고,
개수는 1개이므로 가장 최근의 캔들 1개만 요청하는 쿼리입니다.
위의 같이 수행하면 아쉽게도 아래와 같은 에러가 발생합니다.

{"error":{"name":400,"message":"Missing request parameter error. Check the required parameters!"}}


분명 Open API를 위한 개발자 센터에서 제공된 예제인데,
제대로 동작하지 않는다는게 좀 의아스러기도하고 아쉽기도 합니다.

아무래도 문서화 이후에 API쪽에 변경이 있었나 봅니다.
API 관련된 필드 설명을 살펴보면 마켓 코드가 필수(mandotory)임을 알 수 있습니다.
따라서 위의 쿼리에서 마켓 코드만 넣어주면 정상적으로 캔들 정보가 넘어옵니다.

curl –-request GET \
--url 'https://api.upbit.com/v1/candles/days?count=1&market=KRW-BTC' \
--header 'Accept: application/json'


위와 같이 URL에 조회를 원하는 마켓 정보를 market=KRW-BTC와 같이 추가로 실어주면 캔들 정보를 정상적으로 받아올 수 있습니다.

[{"market":"KRW-BTC","candle_date_time_utc":"2022-03-23T00:00:00","candle_date_time_kst":"2022-03-23T09:00:00","opening_price":51689000.00000000,"high_price":51886000.00000000,"low_price":51300000.00000000,"trade_price":51465000.00000000,"timestamp":1648008580268,"candle_acc_trade_price":57777413849.17576000,"candle_acc_trade_volume":1119.60188760,"prev_closing_price":51704000.00000000,"change_price":-239000.00000000,"change_rate":-0.0046224663}]


출력 결과를 jq '.' 명령으로 예쁘게 찍어주면 아래와 같이 출력됩니다.

[
{
"market": "KRW-BTC",
"candle_date_time_utc": "2022-03-23T00:00:00",
"candle_date_time_kst": "2022-03-23T09:00:00",
"opening_price": 51689000,
"high_price": 51886000,
"low_price": 51300000,
"trade_price": 51465000,
"timestamp": 1648008580268,
"candle_acc_trade_price": 57777413849.17576,
"candle_acc_trade_volume": 1119.6018876,
"prev_closing_price": 51704000,
"change_price": -239000,
"change_rate": -0.0046224663
}
]


출력 결과중에서 시장가인 trade_price를 보려면 'jq .[trace_price]' 명령을 수행하면 됩니다.

curl –-request GET \
--url 'https://api.upbit.com/v1/candles/days?count=1&market=KRW-BTC' \
--header 'Accept: application/json' | jq '.[].trade_price'


아래와 같이 시장가만 깔끔하게 출력되게 됩니다.

51412000


curl 명령을 통한 시세 조회 (python)
["기존 증권사의 API에 비해서 UPbit의 Open API는 아주 편리하게 되어 있습니다. \n캔들 조회는 토큰이 없어도 가능할 뿐만 아니라, \nJavaScript, Python, Ruby, Java 등 다양한 프로그래밍 언어를 이용해서 응용프로그램을 작성할 수 있도록 다양한 예제가 제공됩니다.\n\n본 페이지에서는 업비트 API 중에서도 가장 기본적인 기능인 캔들 조회 기능을 간단하게 구현해보고자 합니다.\n\n본 페이지 작성 환경\n\n이 페이지는 아래 환경을 기준으로 작성되었음을 미리 알려드립니다.\n\n\n \n \n OS\n 프로그래밍 언어\n 비고\n \n \n \n \n Ubuntu Linux\n Python, Curl\n  \n \n \n\n\n업비트 Open API 관련 문서\n\n업비트 Open API 관련 문서는 개발자 센터에서 열람하실 수 있습니다. \n업비트 Open API 개발자 센터\n\n서두에서도 설명드린 것처럼 다양한 언어로 레퍼런스 코드를 제공하기 때문에 \n복사해서 붙여넣기로도 큰 어려움 없이 프로그램을 작성하실 수 있습니다.\n\ncurl 명령을 통한 시세 조회 (curl 명령)\n\n우선 curl 명령을 통해서 캔들 정보를 받아와보겠습니다.\nAPI를 통한 간단한 조회는 웹브라우저나 curl 명령으로도 충분히 수행 가능합니다. \n코드를 작성하거나 그런게 아니므로 처음부터 겁먹을 필요는 없습니다.\n\ncurl --request GET \\\n --url 'https://api.upbit.com/v1/candles/days?count=1' \\\n --header 'Accept: application/json'\n\n\n위의 내용을 잘 살펴보면 일 단위(days)의 캔들(candles)들을 조회하는 명령이고, \n개수는 1개이므로 가장 최근의 캔들 1개만 요청하는 쿼리입니다. \n위의 같이 수행하면 아쉽게도 아래와 같은 에러가 발생합니다.\n\n{\"error\":{\"name\":400,\"message\":\"Missing request parameter error. Check the required parameters!\"}}\n\n\n분명 Open API를 위한 개발자 센터에서 제공된 예제인데, \n제대로 동작하지 않는다는게 좀 의아스러기도하고 아쉽기도 합니다.\n\n아무래도 문서화 이후에 API쪽에 변경이 있었나 봅니다. \nAPI 관련된 필드 설명을 살펴보면 마켓 코드가 필수(mandotory)임을 알 수 있습니다. \n따라서 위의 쿼리에서 마켓 코드만 넣어주면 정상적으로 캔들 정보가 넘어옵니다.\n\ncurl –-request GET \\\n --url 'https://api.upbit.com/v1/candles/days?count=1&market=KRW-BTC' \\\n --header 'Accept: application/json'\n\n\n위와 같이 URL에 조회를 원하는 마켓 정보를 market=KRW-BTC와 같이 추가로 실어주면 캔들 정보를 정상적으로 받아올 수 있습니다.\n\n[{\"market\":\"KRW-BTC\",\"candle_date_time_utc\":\"2022-03-23T00:00:00\",\"candle_date_time_kst\":\"2022-03-23T09:00:00\",\"opening_price\":51689000.00000000,\"high_price\":51886000.00000000,\"low_price\":51300000.00000000,\"trade_price\":51465000.00000000,\"timestamp\":1648008580268,\"candle_acc_trade_price\":57777413849.17576000,\"candle_acc_trade_volume\":1119.60188760,\"prev_closing_price\":51704000.00000000,\"change_price\":-239000.00000000,\"change_rate\":-0.0046224663}]\n\n\n출력 결과를 jq '.' 명령으로 예쁘게 찍어주면 아래와 같이 출력됩니다.\n\n[\n {\n \"market\": \"KRW-BTC\",\n \"candle_date_time_utc\": \"2022-03-23T00:00:00\",\n \"candle_date_time_kst\": \"2022-03-23T09:00:00\",\n \"opening_price\": 51689000,\n \"high_price\": 51886000,\n \"low_price\": 51300000,\n \"trade_price\": 51465000,\n \"timestamp\": 1648008580268,\n \"candle_acc_trade_price\": 57777413849.17576,\n \"candle_acc_trade_volume\": 1119.6018876,\n \"prev_closing_price\": 51704000,\n \"change_price\": -239000,\n \"change_rate\": -0.0046224663\n }\n]\n\n\n출력 결과중에서 시장가인 trade_price를 보려면 'jq .[trace_price]' 명령을 수행하면 됩니다.\n\ncurl –-request GET \\\n --url 'https://api.upbit.com/v1/candles/days?count=1&market=KRW-BTC' \\\n --header 'Accept: application/json' | jq '.[].trade_price'\n\n\n아래와 같이 시장가만 깔끔하게 출력되게 됩니다.\n\n51412000\n\n\ncurl 명령을 통한 시세 조회 (python)\n"]
Title : dead.letter 파일의 정체 (삭제 요망)
URL : /008_ubuntu/005-what-is-dead_letteres.html
Description : Ubuntu Linux 파일 시스템에 생성되는 dead.letter 파일의 정체를 알아보고 어떻게 다뤄야 하는지에 대해서 알아보겠습니다.
Content : dead.letter 파일의 정체는 무엇인가?

회사에서 Ubuntu Linux로 서버를 구축해서 잘 사용중입니다.
퇴근 후 집에서는 라즈베리파이와 Note PC에 Ubuntu Linux를 설치해서
나름 관심있는 분야에 대해서 공부도 하고, 웹서핑도 하는 편입니다.

어느날 회사 서버와 홈 서버에서 이상한 고용량 파일이 발견되기 시작합니다.
파일명은 dead.letter입니다.

$ ls -all dead.letter
-rw-rw-r-- 1 parksejin mail 40554601 Mar 23 06:30 dead.letter


용량은 무려 40MB나 됩니다.
회사 서버에서는 훨씬 더 큰 용량도 목격한 적이 있습니다.

안에 어떤 내용이 들어있을지 너무 궁금해서 열어보기로 했습니다.
vi로 해당 파일을 열어보니 메일 발송해 실패한 메시지들이 가득했습니다.

dead.letter 파일의 일부 (#1. 실패한 crontab 메시지들)

/bin/sh: 1: pushd: not found
/bin/sh: 1: ./auto.sh: not found
/bin/sh: 1: popd: not found


dead.letter 파일을 열어보니 가장 먼저 보이는 것이 실패한 crontab 메시지들입니다.
GitHub Pages의 sitemap과 README.md 파일들을 최신으로 만들어주는 작업을
crontab에 등록해서 수행했습니다.
crontab에서 pushd 명령을 수행할 수 없는 것도 모르고 사용했던 이력이 있는데요.
제대로 동작이 안되었을 뿐만 아니라 불필요하게 dead.letter라는 파일에 실패 로그가 남고 있었던 것입니다.

dead.letter 파일의 일부 (#2. 발송에 실패한 편지들)

<-] 220 smtp.gmail.com ESMTP - gsmtp
36 [->] EHLO esregnet0409@gmail.com
37 [<-] 501 5.5.4 https://support.google.com/mail/?p=helo - gsmtp
38 ssmtp: Cannot open smtp.gmail.com:587


다음으로 목격되는 내용들은 발송에 실패한 메일들입니다.
초기에 보내는 메일 서버 설정이 올바르지 않아서
제대로 발송되지 않았던 이력이 있는데 그게 dead.letter에 쌓이고 있었던 것입니다.

결론

제 결론은요, 삭제가 답입니다.
발송에 실패한 메일들 중에서 중요한 내용은 없어 보입니다.

$ rm dead.letter


이상입니다.
["dead.letter 파일의 정체는 무엇인가?\n\n회사에서 Ubuntu Linux로 서버를 구축해서 잘 사용중입니다. \n퇴근 후 집에서는 라즈베리파이와 Note PC에 Ubuntu Linux를 설치해서 \n나름 관심있는 분야에 대해서 공부도 하고, 웹서핑도 하는 편입니다.\n\n어느날 회사 서버와 홈 서버에서 이상한 고용량 파일이 발견되기 시작합니다. \n파일명은 dead.letter입니다.\n\n$ ls -all dead.letter\n-rw-rw-r-- 1 parksejin mail 40554601 Mar 23 06:30 dead.letter\n\n\n용량은 무려 40MB나 됩니다. \n회사 서버에서는 훨씬 더 큰 용량도 목격한 적이 있습니다.\n\n안에 어떤 내용이 들어있을지 너무 궁금해서 열어보기로 했습니다. \nvi로 해당 파일을 열어보니 메일 발송해 실패한 메시지들이 가득했습니다.\n\ndead.letter 파일의 일부 (#1. 실패한 crontab 메시지들)\n\n/bin/sh: 1: pushd: not found\n/bin/sh: 1: ./auto.sh: not found\n/bin/sh: 1: popd: not found\n\n\ndead.letter 파일을 열어보니 가장 먼저 보이는 것이 실패한 crontab 메시지들입니다. \nGitHub Pages의 sitemap과 README.md 파일들을 최신으로 만들어주는 작업을 \ncrontab에 등록해서 수행했습니다. \ncrontab에서 pushd 명령을 수행할 수 없는 것도 모르고 사용했던 이력이 있는데요. \n제대로 동작이 안되었을 뿐만 아니라 불필요하게 dead.letter라는 파일에 실패 로그가 남고 있었던 것입니다.\n\ndead.letter 파일의 일부 (#2. 발송에 실패한 편지들)\n\n<-] 220 smtp.gmail.com ESMTP - gsmtp\n 36 [->] EHLO esregnet0409@gmail.com\n 37 [<-] 501 5.5.4 https://support.google.com/mail/?p=helo - gsmtp\n 38 ssmtp: Cannot open smtp.gmail.com:587\n\n\n다음으로 목격되는 내용들은 발송에 실패한 메일들입니다. \n초기에 보내는 메일 서버 설정이 올바르지 않아서 \n제대로 발송되지 않았던 이력이 있는데 그게 dead.letter에 쌓이고 있었던 것입니다.\n\n결론\n\n제 결론은요, 삭제가 답입니다. \n발송에 실패한 메일들 중에서 중요한 내용은 없어 보입니다.\n\n$ rm dead.letter\n\n\n이상입니다.\n"]
Title : 라즈베리파이로 GPIO 제어시 RuntimeError: Not running on a RPi 문제 해결 방법 3가지
URL : /010_raspberry/001-not-running-on-RPi.html
Description : 파이선으로 작성한 GPIO 제어 스크립트가 RuntimeError Not running on a RPi라는 메시지와 함께 수행되지 못하는 문제를 해결하는 방법 설명
Content : 라즈베리파이로 가장 먼저 손쉽게 제어할 수 있는 것이 바로 GPIO 블록입니다.
그 중에서도 GPO를 통해서 신호를 출력하는 방법은 단 몇 줄이면 충분합니다.
아주 간단하게 LED를 켜거나 끌 수 있습니다.

하지만 간혹 의도하지 않은 에러가 발생하기도 합니다.
아주 간단한 실수임에도 불구하고, 그 원인을 어렵게 찾아내는 경우가 많습니다.
본 페이지에서는 “RuntimeError: Not running on a RPi!” 에러가 발생했을 때 시도해볼 수 있는 방법 3가지를 제공합니다.

첫번째 방법 : 재부팅

제대로 동작하지 않을때 많이 시도해보는 방법입니다.
좋은 방법은 아니지만 뛰어난 효과가 있을 때가 많습니다.

$ sudo reboot


두번째 방법 : 파이선 GPIO 패키지 설치

라즈베리파이를 처음 시작했거나, OS를 새로 설치했다면 패키지가 설치되지 않아서 발생하는 문제일 수 있습니다.
아래의 명령을 통해서 파이선의 GPIO 패키지를 설치합니다.

$ sudo apt-get install python3-rpi.gpio


세번째 방법 : sudo 권한으로 파이선 스크립트 실행

GPIO를 제어하는 것은 관리자 권한이 필요합니다.
이 때문에 GPIO를 제어하는 파이선 스크립트 실행시에 sudo를 입력하지 않으면 이런 에러가 발생할 수 있습니다.
이 때는 아래와 같이 sudo를 추가하여 파이선 스크립트를 수행시켜주면 됩니다.

$ sudo python3 gpio_control.py


결론

본 페이지에서는 라즈베리파이에서 “RuntimeError: Not running on a RPi!” 에러가 발생했을 때 조치할 수 있는 3가지 방법에 대해서 알아보았습니다.
["라즈베리파이로 가장 먼저 손쉽게 제어할 수 있는 것이 바로 GPIO 블록입니다. \n그 중에서도 GPO를 통해서 신호를 출력하는 방법은 단 몇 줄이면 충분합니다. \n아주 간단하게 LED를 켜거나 끌 수 있습니다.\n\n하지만 간혹 의도하지 않은 에러가 발생하기도 합니다. \n아주 간단한 실수임에도 불구하고, 그 원인을 어렵게 찾아내는 경우가 많습니다.\n본 페이지에서는 “RuntimeError: Not running on a RPi!” 에러가 발생했을 때 시도해볼 수 있는 방법 3가지를 제공합니다.\n\n첫번째 방법 : 재부팅\n\n제대로 동작하지 않을때 많이 시도해보는 방법입니다. \n좋은 방법은 아니지만 뛰어난 효과가 있을 때가 많습니다.\n\n$ sudo reboot\n\n\n두번째 방법 : 파이선 GPIO 패키지 설치\n\n라즈베리파이를 처음 시작했거나, OS를 새로 설치했다면 패키지가 설치되지 않아서 발생하는 문제일 수 있습니다. \n아래의 명령을 통해서 파이선의 GPIO 패키지를 설치합니다.\n\n$ sudo apt-get install python3-rpi.gpio\n\n\n세번째 방법 : sudo 권한으로 파이선 스크립트 실행\n\nGPIO를 제어하는 것은 관리자 권한이 필요합니다. \n이 때문에 GPIO를 제어하는 파이선 스크립트 실행시에 sudo를 입력하지 않으면 이런 에러가 발생할 수 있습니다. \n이 때는 아래와 같이 sudo를 추가하여 파이선 스크립트를 수행시켜주면 됩니다.\n\n$ sudo python3 gpio_control.py\n\n\n결론\n\n본 페이지에서는 라즈베리파이에서 “RuntimeError: Not running on a RPi!” 에러가 발생했을 때 조치할 수 있는 3가지 방법에 대해서 알아보았습니다.\n"]
Title : GitHub Pages 빌드 에러 Error No uploaded artifact was found. Please check if there are any errors at build step.
URL : /002_github_blog/010-github-no-uploaded-artifact-was-found.html
Description : GitHub Pages에서 빌드 에러가 발생시에 조치하는 방법에 대해서 설명합니다.
Content : 최근에 GitHub Pages를 이용해서 웹페이지를 구성하였고,
글쓰기의 재미에 푹 빠져있습니다.
GitHub Pages는 무척 흥미로운 무료 웹서버로 참 매력적인 서비스임에 틀림없습니다.
새로운 글들을 생산해내는 도중에 생경한 에러를 만나고야 말았습니다.

문제의 상황 파악

GitHub Pages에 연결된 레포지토리의 Actions에 빨간불이 떠 있는게 아니겠습니까? 자세히 들어가서 살펴보니 아래와 같은 에러 메시지가 발견됩니다.

Error: No uploaded artifact was found! Please check if there are any errors at build step.


GitHub Pages에 연결된 레포지토리에 commit 또는 push를 하게되면,
내부적으로 빌드(Build) 과정을 거쳐서 웹서버에 반영(Deploy)됩니다.
컨텐츠 중에서 업로드 되지 않은 항목이 있으니,
빌드 과정에서 에러가 있는지 확인해보라는 메시지입니다.

빌드 로그를 살펴보니 아래와 같은 메시지가 발견됩니다.

Error reading file /github/workspace/006_java/001.md: invalid byte sequence in UTF-8
Conversion error: Jekyll::Converters::Markdown encountered an error while converting '006_java/001.md':
The source text contains invalid characters for the used encoding UTF-8


문제가 되는 파일은 /006\_java/001.md라는 파일에서 발생을 했고,
UTF-8형식으로 처리할 수 없는 문자가 포함되어 있다는 메시지였습니다.
실제로 해당 파일을 열어보니 파일이 깨져 있었습니다.

빌드 에러가 아니라 deploy 에러라면?

만약 build 단계의 에러가 아니라 deploy 단계의 에러라면
아래의 페이지를 참조하시기 바랍니다.

GitHub Pages deploy 에러 발생

문제의 해결

문제가 되는 파일을 삭제하고 수정 사항을 push 했더니
정상적으로 빌드 및 업로드가 된 것을 확인할 수 있었습니다.

결론

만약 GitHub Pages에서 빌드 및 업로드 에러가 발생한다면,
Encoding 형식에 맞지 않는 문자가 md 파일에 포함되었는지 확인해보시기 바랍니다.

파일이 깨져있거나, 처리할 수 없는 문자가 있을 경우 해당 파일을 삭제하고 push하면 정상적으로 빌드되는 것을 확인하실 수 있습니다.

이상입니다.
["최근에 GitHub Pages를 이용해서 웹페이지를 구성하였고, \n글쓰기의 재미에 푹 빠져있습니다. \nGitHub Pages는 무척 흥미로운 무료 웹서버로 참 매력적인 서비스임에 틀림없습니다. \n새로운 글들을 생산해내는 도중에 생경한 에러를 만나고야 말았습니다.\n\n문제의 상황 파악\n\nGitHub Pages에 연결된 레포지토리의 Actions에 빨간불이 떠 있는게 아니겠습니까? 자세히 들어가서 살펴보니 아래와 같은 에러 메시지가 발견됩니다.\n\nError: No uploaded artifact was found! Please check if there are any errors at build step.\n\n\nGitHub Pages에 연결된 레포지토리에 commit 또는 push를 하게되면, \n내부적으로 빌드(Build) 과정을 거쳐서 웹서버에 반영(Deploy)됩니다. \n컨텐츠 중에서 업로드 되지 않은 항목이 있으니, \n빌드 과정에서 에러가 있는지 확인해보라는 메시지입니다.\n\n빌드 로그를 살펴보니 아래와 같은 메시지가 발견됩니다.\n\nError reading file /github/workspace/006_java/001.md: invalid byte sequence in UTF-8 \n Conversion error: Jekyll::Converters::Markdown encountered an error while converting '006_java/001.md':\n The source text contains invalid characters for the used encoding UTF-8\n\n\n문제가 되는 파일은 /006\\_java/001.md라는 파일에서 발생을 했고, \nUTF-8형식으로 처리할 수 없는 문자가 포함되어 있다는 메시지였습니다. \n실제로 해당 파일을 열어보니 파일이 깨져 있었습니다.\n\n빌드 에러가 아니라 deploy 에러라면?\n\n만약 build 단계의 에러가 아니라 deploy 단계의 에러라면 \n아래의 페이지를 참조하시기 바랍니다.\n\nGitHub Pages deploy 에러 발생\n\n문제의 해결\n\n문제가 되는 파일을 삭제하고 수정 사항을 push 했더니 \n정상적으로 빌드 및 업로드가 된 것을 확인할 수 있었습니다.\n\n결론\n\n만약 GitHub Pages에서 빌드 및 업로드 에러가 발생한다면, \nEncoding 형식에 맞지 않는 문자가 md 파일에 포함되었는지 확인해보시기 바랍니다.\n\n파일이 깨져있거나, 처리할 수 없는 문자가 있을 경우 해당 파일을 삭제하고 push하면 정상적으로 빌드되는 것을 확인하실 수 있습니다.\n\n이상입니다.\n"]
Title : mapping values are not allwed in this context at line 2 column 33 해결 방법
URL : /002_github_blog/011-github-mapping-values-are-not-allowed-in-this-context.html
Description : GitHub Pages의 md 파일 상단에 YAML 형식의 헤더를 추가했을 때 발생하는 mapping values are not allwed in this context at line 2 column 33에러를 조치하는 방법에 대해서 설명한다.
Content : 지난 시간에 GitHub Pages가 더 잘 검색되도록 하기 위해서
md 파일의 상단에 아래와 같은 형식으로 title과 description의 YAML 형식의 헤더를 추가하는 방법에 대해서 언급했다.

---
title: 제목으로 사용할 문자열
description: 페이지에 대한 설명으로 사용할 문자열
---


위와 같이 GitHub Pages의 md 파일 상단에 해당 내용을 추가하면,
HTML로 변환된 페이지의 헤더에 Title과 Description 테크가 적절하게 갱신되기 때문에 검색 엔진으로부터 더욱 잘 노출될 가능성이 높다.

하지만 위의 형식으로 입력한 컨텐츠들 중에서 아래와 같은 에러를 띄워서
빌드시에 경고 메시지로 표시되는 경우가 더러 있다.

mapping values are not allowed in this context at line 2 column 33


실제 해당 파일을 찾아가보면 내용에 쌍따옴표(")가 있어서 발생하는 경우가 많다.

---
title: "mapping values are not allwed in this context at line 2 column 33" 해
결 방법
---


\"를 \\\"로 바꾸면 이 문제가 해결된다.

---
title: \"mapping values are not allwed in this context at line 2 column 33\" 해
결 방법
---


또한 전체 내용을 작은 따옴표 안에 인용하는 것도 하나의 방법이다.
단, 작은 따옴표(‘) 안에 넣는 내용에 작은 따옴표(‘)가 있어서는 안된다.
작은 따옴표를 중첩해서 사용할 수 없다.

문제점을 수정하고 push 하면 정상적으로 빌드 및 발행이 되는 것을 확인할 수 있다.

Invalid scheme format 에러 발생 시 조치 방법

Invalid scheme format 에러가 발생할 경우 렌더링을 지원하지 않는 파일 포맷에 의한 것일 수 있다.

Error: Invalid scheme format: '2022-03-23T00'


만약 위와 같은 에러가 빌드 과정에서 확인되면,
파일명에 :가 포함되어 있지는 않은지 확인이 필요하다.

필자의 경우 자동으로 생성되는 페이지들이 있는데,
이 파일명에 :가 포함되어 있어서 빌드에 실패했다.

2022-03-23T00:00:00.md와 같이 :가 포함된 부분을 수정했더니,
정상적으로 빌드가 되는 것을 확인할 수 있었다.

결론

만약 GitHub Pages의 헤더에 작성하는 YAML 형식의 정보에서 “mapping value are not allowed in this context at line 2 column 33”과 같은 에러가 빌드시에 발생한다면 값에 따옴표가 있는건 아닌지 살펴보자.

또한, ‘:’와 같은 문자도 허용되지 않기 때문에 주의가 필요하다.
["지난 시간에 GitHub Pages가 더 잘 검색되도록 하기 위해서 \nmd 파일의 상단에 아래와 같은 형식으로 title과 description의 YAML 형식의 헤더를 추가하는 방법에 대해서 언급했다.\n\n---\ntitle: 제목으로 사용할 문자열\ndescription: 페이지에 대한 설명으로 사용할 문자열\n---\n\n\n위와 같이 GitHub Pages의 md 파일 상단에 해당 내용을 추가하면, \nHTML로 변환된 페이지의 헤더에 Title과 Description 테크가 적절하게 갱신되기 때문에 검색 엔진으로부터 더욱 잘 노출될 가능성이 높다.\n\n하지만 위의 형식으로 입력한 컨텐츠들 중에서 아래와 같은 에러를 띄워서 \n빌드시에 경고 메시지로 표시되는 경우가 더러 있다.\n\nmapping values are not allowed in this context at line 2 column 33 \n\n\n실제 해당 파일을 찾아가보면 내용에 쌍따옴표(\")가 있어서 발생하는 경우가 많다.\n\n---\ntitle: \"mapping values are not allwed in this context at line 2 column 33\" 해\n결 방법\n---\n\n\n\\\"를 \\\\\\\"로 바꾸면 이 문제가 해결된다.\n\n---\ntitle: \\\"mapping values are not allwed in this context at line 2 column 33\\\" 해\n결 방법\n---\n\n\n또한 전체 내용을 작은 따옴표 안에 인용하는 것도 하나의 방법이다. \n단, 작은 따옴표(‘) 안에 넣는 내용에 작은 따옴표(‘)가 있어서는 안된다. \n작은 따옴표를 중첩해서 사용할 수 없다.\n\n문제점을 수정하고 push 하면 정상적으로 빌드 및 발행이 되는 것을 확인할 수 있다.\n\nInvalid scheme format 에러 발생 시 조치 방법\n\nInvalid scheme format 에러가 발생할 경우 렌더링을 지원하지 않는 파일 포맷에 의한 것일 수 있다.\n\nError: Invalid scheme format: '2022-03-23T00'\n\n\n만약 위와 같은 에러가 빌드 과정에서 확인되면, \n파일명에 :가 포함되어 있지는 않은지 확인이 필요하다.\n\n필자의 경우 자동으로 생성되는 페이지들이 있는데, \n이 파일명에 :가 포함되어 있어서 빌드에 실패했다.\n\n2022-03-23T00:00:00.md와 같이 :가 포함된 부분을 수정했더니, \n정상적으로 빌드가 되는 것을 확인할 수 있었다.\n\n결론\n\n만약 GitHub Pages의 헤더에 작성하는 YAML 형식의 정보에서 “mapping value are not allowed in this context at line 2 column 33”과 같은 에러가 빌드시에 발생한다면 값에 따옴표가 있는건 아닌지 살펴보자.\n\n또한, ‘:’와 같은 문자도 허용되지 않기 때문에 주의가 필요하다.\n"]
Title : 모질라 썬더버드 메일 설정 방법 (네이버, gmail, 다음, 네이트)
URL : /008_ubuntu/004-thunderbird-email-setting-naver-gmail-daum.html
Description : Ubuntu Linux에서 기본적으로 제공하는 메일 프로그램인 모질라 썬더버드에 개인 메일 계정을 연결 방법을에 설명합니다.
Content : 일전에 유사한 내용으로 기록해둔적이 있는데 메일 서비스의 주소와 설정 방법에 조금씩 달라져서 이번에 일목요연하게 정리하고자 합니다.




메일 서비스
보내는 서버
포트 번호
받는 서버
포트 번호
비고




네이버
smtp.naver.com
465
pop.naver.com
995
 


gmail
smtp.gmail.com
465
imap.gmail.com
993
썬더버드에서 지메일은 자동으로 설정됨


다음
smtp.daum.net
465
imap.daum.net
993
 


네이트
smtp.mail.nate.com
465
pop3.nate.com
995
 




마지막 업데이트 날짜 : 2022년 3월 22일
["일전에 유사한 내용으로 기록해둔적이 있는데 메일 서비스의 주소와 설정 방법에 조금씩 달라져서 이번에 일목요연하게 정리하고자 합니다.\n\n\n \n \n 메일 서비스\n 보내는 서버\n 포트 번호\n 받는 서버\n 포트 번호\n 비고\n \n \n \n \n 네이버\n smtp.naver.com\n 465\n pop.naver.com\n 995\n  \n \n \n gmail\n smtp.gmail.com\n 465\n imap.gmail.com\n 993\n 썬더버드에서 지메일은 자동으로 설정됨\n \n \n 다음\n smtp.daum.net\n 465\n imap.daum.net\n 993\n  \n \n \n 네이트\n smtp.mail.nate.com\n 465\n pop3.nate.com\n 995\n  \n \n \n\n\n마지막 업데이트 날짜 : 2022년 3월 22일\n"]
Title : GitHub Pages 운영시의 꿀팁들
URL : /002_github_blog/008.html
Description : GitHub Pages를 운영하면서 체득한 유용한 팁들을 제공합니다.
Content : GitHub Pages를 이용해서 웹페이지를 운영하기 시작한지 2주가 좀 지났습니다.
처음에는 전혀 개념을 잡지 못해서 제법 시간과 노력이 필요했습니다.
GitHub에는 익숙한 SW 개발자이지만 jekyll이 어떻게 빌드되고 웹페이지가 생성되는지 파악하는데 제법 시간이 소요되었습니다.
본 페이지에선 그 동안 GitHub Pages를 생성하면서 알게된 소소한 꿀팁들을 기록해두고자 합니다.

Jekyll 빌드란?

저는 네이버 블로그, 티스토리 블로그, 직접 웹서버 운영 등을 모두 해봤습니다.
하지만 Jekyll이 무엇인지에 대한 개념은 전혀 없었기 때문에,
GitHub Pages를 어떻게 작서해야 하는지에 대한 개념이 전혀 없었습니다.

README.md 파일은 자동으로 index.html로 빌드됨

가장 기본적인 Jekyll 빌드 과정에 대해서 설명을 드리자면,
README.md 파일을 작성하면 잠시후 빌드 과정을 거쳐서 index.html 파일이 생성됩니다.
GitHub Pages에 익숙하지 않으신 분들은 Repository에 index.html 파일이 없는데 어떻게 index.html로 접속이 되는지 뇌의 회로가 정지되는 듯한 느낌을 느낄 수 있겠습니다.

md 확장자를 가진 파일은 자동으로 html 파일로 빌드됨

방금 READMD.md 파일이 존재하면 자동으로 index.html 파일을 생성시킨다는 것을 알 수 있습니다.
그렇다면 다른 페이지들은 어떻게 작성하면 될까요?
그냥 md 파일을 작성해서 GitHub에 push되면 자동으로 html 파일이 생성되게 됩니다.
즉. abc.md 파일을 작성해서 GitHub Pages에 업데이트하셨다면 잠시 후에 abc.html 파일이 생성되어서 게시가 가능하다는 것을 알 수 있습니다.

즉, GitHub repository에 있는 파일들을 기반으로 html 파일들이 생성되고, 웹서버에서 해당 파일들을 서비스할 수 있게 됩니다.




repisotory
Web Server
비고




/README.md
/README.md
README.md 파일을 repo에도 있고 웹서버에도 있음


 
/index.html
/README.md 파일에 의해서 생성된 index.html 파일은 웹서버에만 존재


/abc.md
/abc.md
md 확장자의 파일은 repo에도 존재하고 웹서버에도 존재함


 
/abc.html
md 파일에 의해서 생성된 html 파일은 웹서버에만 존재함


/_include/sample.html
 
_로 시작되는 디렉토리는 빌드되지 않음




빌드되지 않도록 지정해주는 방법

Jekyll은 특정한 디렉토리나 파일들은 빌드하지 않습니다.

아래와 같이 작명된 디렉토리나 파일은 Jekyll이 빌드하지 않습니다.
만약, Jekyll이 빌드하지 않도록 하고 싶다면 아래와 같이 설정해보시기 바랍니다.


/node\_modules 혹은 /vendor 디렉토리
\_ 혹은 . 혹은 #로 시작하는 디렉토리나 파일들
\~로 끝나는 파일들
설정 파일에서 exclude로 지정된 디렉토리나 파일들


반대로 위와 같이 작명된 디렉토리나 파일들 중에서 빌드되도록 지정하고 싶다면,
include 설정을 환경 설정 파일에 추가하시면 됩니다.

만약 Jekyll 빌드를 원치 않을 경우

만약 GitHub Pages 전체를 Jekyll 빌드되지 않도록 하고 싶다면
.nojekyll 파일을 루트 디렉토리에 생성하면 됩니다.
파일 내용은 상관 없습니다.
["GitHub Pages를 이용해서 웹페이지를 운영하기 시작한지 2주가 좀 지났습니다. \n처음에는 전혀 개념을 잡지 못해서 제법 시간과 노력이 필요했습니다. \nGitHub에는 익숙한 SW 개발자이지만 jekyll이 어떻게 빌드되고 웹페이지가 생성되는지 파악하는데 제법 시간이 소요되었습니다. \n본 페이지에선 그 동안 GitHub Pages를 생성하면서 알게된 소소한 꿀팁들을 기록해두고자 합니다.\n\nJekyll 빌드란?\n\n저는 네이버 블로그, 티스토리 블로그, 직접 웹서버 운영 등을 모두 해봤습니다. \n하지만 Jekyll이 무엇인지에 대한 개념은 전혀 없었기 때문에, \nGitHub Pages를 어떻게 작서해야 하는지에 대한 개념이 전혀 없었습니다.\n\nREADME.md 파일은 자동으로 index.html로 빌드됨\n\n가장 기본적인 Jekyll 빌드 과정에 대해서 설명을 드리자면, \nREADME.md 파일을 작성하면 잠시후 빌드 과정을 거쳐서 index.html 파일이 생성됩니다. \nGitHub Pages에 익숙하지 않으신 분들은 Repository에 index.html 파일이 없는데 어떻게 index.html로 접속이 되는지 뇌의 회로가 정지되는 듯한 느낌을 느낄 수 있겠습니다.\n\nmd 확장자를 가진 파일은 자동으로 html 파일로 빌드됨\n\n방금 READMD.md 파일이 존재하면 자동으로 index.html 파일을 생성시킨다는 것을 알 수 있습니다. \n그렇다면 다른 페이지들은 어떻게 작성하면 될까요? \n그냥 md 파일을 작성해서 GitHub에 push되면 자동으로 html 파일이 생성되게 됩니다. \n즉. abc.md 파일을 작성해서 GitHub Pages에 업데이트하셨다면 잠시 후에 abc.html 파일이 생성되어서 게시가 가능하다는 것을 알 수 있습니다.\n\n즉, GitHub repository에 있는 파일들을 기반으로 html 파일들이 생성되고, 웹서버에서 해당 파일들을 서비스할 수 있게 됩니다.\n\n\n \n \n repisotory\n Web Server\n 비고\n \n \n \n \n /README.md\n /README.md\n README.md 파일을 repo에도 있고 웹서버에도 있음\n \n \n  \n /index.html\n /README.md 파일에 의해서 생성된 index.html 파일은 웹서버에만 존재\n \n \n /abc.md\n /abc.md\n md 확장자의 파일은 repo에도 존재하고 웹서버에도 존재함\n \n \n  \n /abc.html\n md 파일에 의해서 생성된 html 파일은 웹서버에만 존재함\n \n \n /_include/sample.html\n  \n _로 시작되는 디렉토리는 빌드되지 않음\n \n \n\n\n빌드되지 않도록 지정해주는 방법\n\nJekyll은 특정한 디렉토리나 파일들은 빌드하지 않습니다.\n\n아래와 같이 작명된 디렉토리나 파일은 Jekyll이 빌드하지 않습니다. \n만약, Jekyll이 빌드하지 않도록 하고 싶다면 아래와 같이 설정해보시기 바랍니다.\n\n\n /node\\_modules 혹은 /vendor 디렉토리\n \\_ 혹은 . 혹은 #로 시작하는 디렉토리나 파일들\n \\~로 끝나는 파일들\n 설정 파일에서 exclude로 지정된 디렉토리나 파일들\n\n\n반대로 위와 같이 작명된 디렉토리나 파일들 중에서 빌드되도록 지정하고 싶다면, \ninclude 설정을 환경 설정 파일에 추가하시면 됩니다.\n\n만약 Jekyll 빌드를 원치 않을 경우\n\n만약 GitHub Pages 전체를 Jekyll 빌드되지 않도록 하고 싶다면 \n.nojekyll 파일을 루트 디렉토리에 생성하면 됩니다. \n파일 내용은 상관 없습니다.\n"]
Title : SEO를 위해 GitHub Pages 의 md 파일에 헤더를 입력하는 방법
URL : /002_github_blog/009.html
Description : GitHub Pages의 markdown 파일의 헤더에 title, description을 지정하는 방법에 대해서 설명합니다.
Content : 왜 GitHub Pages에 title과 description을 추가해야 하나?

웹 페이지를 생성해서 운영하는 사람이라면 누구나 더 많은 트래픽이 유입되기를 원할 것입니다.
이것이 바로 우리가 웹페이지를 생성해서 운영하는 이유이기 때문입니다.
더 많은 트래픽이 발생할수록, 더 많은 광고 수익을 올릴 수 있기 때문입니다.

Google에서는 200가지가 넘는 데이터를 이용해서 사이트별로 순위를 메긴다고 합니다.
구글 검색 엔진이 웹 페이지의 데이터를 수집해갈때 제목이나 설명 등의 내용을 파악하는데 도움을 주는 것이 바로 SEO입니다.

GitHub Pages를 작성할 때 아래와 같이 헤더를 작성해주면 Jekyll은 이 헤더 정보를 빌드해서 html 파일을 생성하고,
구글을 포함한 다양한 검색 엔진들은 이 페이지가 어떤 내용을 담고 있는지 좀 더 쉽게 정형화된 방법으로 수집해갈 수 있는 것이지요.

GitHub Pages 작성시 파일 헤더 포맷

---
title: 이 페이지의 제목
description: 이 페이지에 대한 요약
---


위와 같은 포맷으로 md 파일을 작성하고 업데이트하면
잠시후에 생성되는 html파일의 헤더에 meta 테그가
포함되어 있는 것을 확인할 수 있습니다.

<head>

["왜 GitHub Pages에 title과 description을 추가해야 하나?\n\n웹 페이지를 생성해서 운영하는 사람이라면 누구나 더 많은 트래픽이 유입되기를 원할 것입니다. \n이것이 바로 우리가 웹페이지를 생성해서 운영하는 이유이기 때문입니다. \n더 많은 트래픽이 발생할수록, 더 많은 광고 수익을 올릴 수 있기 때문입니다.\n\nGoogle에서는 200가지가 넘는 데이터를 이용해서 사이트별로 순위를 메긴다고 합니다. \n구글 검색 엔진이 웹 페이지의 데이터를 수집해갈때 제목이나 설명 등의 내용을 파악하는데 도움을 주는 것이 바로 SEO입니다.\n\nGitHub Pages를 작성할 때 아래와 같이 헤더를 작성해주면 Jekyll은 이 헤더 정보를 빌드해서 html 파일을 생성하고, \n구글을 포함한 다양한 검색 엔진들은 이 페이지가 어떤 내용을 담고 있는지 좀 더 쉽게 정형화된 방법으로 수집해갈 수 있는 것이지요.\n\nGitHub Pages 작성시 파일 헤더 포맷\n\n---\ntitle: 이 페이지의 제목\ndescription: 이 페이지에 대한 요약\n---\n\n\n위와 같은 포맷으로 md 파일을 작성하고 업데이트하면 \n잠시후에 생성되는 html파일의 헤더에 meta 테그가 \n포함되어 있는 것을 확인할 수 있습니다.\n\n <head>\n\n"]
Title : GitHub에서 레포지토리의 생성일을 확인하는 방법
URL : /001_github_api/004-github-how-to-get-the-creation-date-of-repository.html
Description : GitHub API를 이용해서 레포지토리의 생성일을 확인하는 방법에 대해서 설명합니다.
Content : GitHub Pages를 생성하고 16일만에 구글의 애드센스를 게시할 수 있게 되었습니다.
웹 페이지를 처음 생성한 초기에는 사용법에 익숙하지 않아서 많이 힘들었습니다.
아시다시피 GitHub Pages는 GitHub에서 관리되는 웹서버입니다.
무료로 사용할 수 있는데다가 GitHub의 형상 관리 기능을 그대로 사용할 수 있기 때문에 컨텐츠 관리에도 효율적입니다.

나름 SW 개발을 약 15년 가까이 하고 있어서 GitHub에 상당히 익숙하니다만,
GitHub Pages용 레포지토리를 언제 생성했는지 막상 확인하려 했더니 어떻게 확인해야 될지 조금 막막하더군요.
API 호출을 통해서 깃헙 저장소의 생성일을 확인할 수 있는 방법에 대해서 설명드리겠습니다.

GitHub API를 이용해서 레포지토리의 생성일을 확인하는 방법 (웹브라우저 이용)

GitHub API를 이용하면 레포지토리의 생성일을 손쉽게 확인할 수 있습니다.
난이도는 아주 낮기 때문에 누구든지 어렵지 않게 확인할 수 있습니다.
웹브라우저에 아래와 같은 형식으로 입력해보면 됩니다.

https://api.github.com/repos/{username}/{repository name}


예를 들어서 username이 boyinblue이고, repo명이 boyinblue.github.io 라면 아래와 같이 입력하면 됩니다.

https://api.github.com/repos/boyinblue/boyinblue.github.io


실행 결과는 아래와 같습니다.



GitHub API의 응답은 json 형식으로 리턴됩니다.
그 중에서도 “created_at” 항목을 보시면 언제 생성되었는지 확인하실 수 있습니다.

"releases_url": "https://api.github.com/repos/boyinblue/boyinblue.github.io/releases{/id}",
"deployments_url": "https://api.github.com/repos/boyinblue/boyinblue.github.io/deployments",
"created_at": "2022-03-06T06:20:09Z",
"updated_at": "2022-03-21T15:23:44Z",
"pushed_at": "2022-03-22T00:25:25Z",
"git_url": "git://github.com/boyinblue/boyinblue.github.io.git",
"ssh_url": "git@github.com:boyinblue/boyinblue.github.io.git",
"clone_url": "https://github.com/boyinblue/boyinblue.github.io.git",
"svn_url": "https://github.com/boyinblue/boyinblue.github.io",


제 GitHub Pages는 2022년 3월 6일에 생성되었다는 것을 확인할 수 있습니다.

GitHub API를 이용해서 레포지토리의 생성일을 확인하는 방법 (curl 명령 이용)

위와 같이 웹브라우저에서 확인하는 방법은 다소 불편함이 있습니다.
사람이 손으로 웹브라우저에 주소를 입력해줘야하고, 그 결과도 찾아봐야되기 때문입니다.
우선 웹브라우저 없이 curl 명령을 통해서 확인하는 방법에 대해서 설명드리겠습니다.
웹 브라우저에 입력했던 URL을 curl 명령 인자로 넣어주기만 하면 됩니다.

$ curl https://api.github.com/repos/boyinblue/boyinblue.github.io


아까 웹브라우저로 살펴봤던 내용과 동일한 내용이 json으로 출력됩니다.
다음 단계는, 출력되는 json 중에서 필요한 내용만 추출하는 것입니다.
Ubuntu Linux 기준으로 jq라는 패키지를 사용하면 손쉽게 파싱할 수 있습니다.

혹시 jq 패키지가 설치되어 있지 않다면 $ sudo apt-get install jq 명령을 통해서 설치해줍니다.
이미 jq 패키ㅣ가 설치되어 있다면 아래 과정은 생략하시면 됩니다.

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install jq


설치가 완료되었는지 확인하기 위해서 jq --version 명령을 입력해줍니다.

$ jq --version


패키지가 제대로 설치되었다면 아래와 같이 jq 패키지의 버전이 표시되게 됩니다.

jq-1.6


이제 본격적으로 jq를 이용해서 레포의 생성일을 확인할 차례입니다.

$ curl https://api.github.com/repos/boyinblue/boyinblue.github.io | jq '.created_at'


레포지토리의 생성일이 UTC(세계 협정시)를 기준으로 표기됩니다.

"2022-03-06T06:20:09Z"


실행 결과를 살펴보면 json 데이터 중에서 created_at 이라는 항목만 표시된 것을 알 수 있습니다.
crul 명령을 통해서 표준출력으로 튀어나오는 json 데이터를 다시 파이프를 통해서 jq에 공급해주는 명령입니다.
jq는 json 데이터중에서 created_at 항목만 추출해서 출력해줍니다.

한가지 아쉬운 점은 결과값이 쌍따움표 안에 표기되어 있다는 것입니다.
쌍다움표를 제거시키기 위해서 xargs 라는 명령을 사용하겠습니다.

$ curl https://api.github.com/repos/boyinblue/boyinblue.github.io | jq '.created_at' | xargs


위와 같이 수행하면 쌍따움표가 제거된 상태로 레포지토리의 생성일이 출력됩니다.

2022-03-06T06:20:09Z


xargs 명령을 거치면서 쌍따움표가 제거되어 원하는대로 깔끔하게 출력되었습니다.

결론

본 페이지에서는 GitHub Repoitory의 생성일을 확인하는 방법에 대해서 살펴보았습니다.

이상입니다.
["GitHub Pages를 생성하고 16일만에 구글의 애드센스를 게시할 수 있게 되었습니다. \n웹 페이지를 처음 생성한 초기에는 사용법에 익숙하지 않아서 많이 힘들었습니다. \n아시다시피 GitHub Pages는 GitHub에서 관리되는 웹서버입니다. \n무료로 사용할 수 있는데다가 GitHub의 형상 관리 기능을 그대로 사용할 수 있기 때문에 컨텐츠 관리에도 효율적입니다.\n\n나름 SW 개발을 약 15년 가까이 하고 있어서 GitHub에 상당히 익숙하니다만, \nGitHub Pages용 레포지토리를 언제 생성했는지 막상 확인하려 했더니 어떻게 확인해야 될지 조금 막막하더군요. \nAPI 호출을 통해서 깃헙 저장소의 생성일을 확인할 수 있는 방법에 대해서 설명드리겠습니다.\n\nGitHub API를 이용해서 레포지토리의 생성일을 확인하는 방법 (웹브라우저 이용)\n\nGitHub API를 이용하면 레포지토리의 생성일을 손쉽게 확인할 수 있습니다. \n난이도는 아주 낮기 때문에 누구든지 어렵지 않게 확인할 수 있습니다. \n웹브라우저에 아래와 같은 형식으로 입력해보면 됩니다.\n\nhttps://api.github.com/repos/{username}/{repository name}\n\n\n예를 들어서 username이 boyinblue이고, repo명이 boyinblue.github.io 라면 아래와 같이 입력하면 됩니다.\n\nhttps://api.github.com/repos/boyinblue/boyinblue.github.io\n\n\n실행 결과는 아래와 같습니다.\n\n\n\nGitHub API의 응답은 json 형식으로 리턴됩니다. \n그 중에서도 “created_at” 항목을 보시면 언제 생성되었는지 확인하실 수 있습니다.\n\n \"releases_url\": \"https://api.github.com/repos/boyinblue/boyinblue.github.io/releases{/id}\",\n \"deployments_url\": \"https://api.github.com/repos/boyinblue/boyinblue.github.io/deployments\",\n \"created_at\": \"2022-03-06T06:20:09Z\",\n \"updated_at\": \"2022-03-21T15:23:44Z\",\n \"pushed_at\": \"2022-03-22T00:25:25Z\",\n \"git_url\": \"git://github.com/boyinblue/boyinblue.github.io.git\",\n \"ssh_url\": \"git@github.com:boyinblue/boyinblue.github.io.git\",\n \"clone_url\": \"https://github.com/boyinblue/boyinblue.github.io.git\",\n \"svn_url\": \"https://github.com/boyinblue/boyinblue.github.io\",\n\n\n제 GitHub Pages는 2022년 3월 6일에 생성되었다는 것을 확인할 수 있습니다.\n\nGitHub API를 이용해서 레포지토리의 생성일을 확인하는 방법 (curl 명령 이용)\n\n위와 같이 웹브라우저에서 확인하는 방법은 다소 불편함이 있습니다. \n사람이 손으로 웹브라우저에 주소를 입력해줘야하고, 그 결과도 찾아봐야되기 때문입니다. \n우선 웹브라우저 없이 curl 명령을 통해서 확인하는 방법에 대해서 설명드리겠습니다. \n웹 브라우저에 입력했던 URL을 curl 명령 인자로 넣어주기만 하면 됩니다.\n\n$ curl https://api.github.com/repos/boyinblue/boyinblue.github.io\n\n\n아까 웹브라우저로 살펴봤던 내용과 동일한 내용이 json으로 출력됩니다. \n다음 단계는, 출력되는 json 중에서 필요한 내용만 추출하는 것입니다. \nUbuntu Linux 기준으로 jq라는 패키지를 사용하면 손쉽게 파싱할 수 있습니다.\n\n혹시 jq 패키지가 설치되어 있지 않다면 $ sudo apt-get install jq 명령을 통해서 설치해줍니다.\n이미 jq 패키ㅣ가 설치되어 있다면 아래 과정은 생략하시면 됩니다.\n\n$ sudo apt-get update\n$ sudo apt-get upgrade\n$ sudo apt-get install jq\n\n\n설치가 완료되었는지 확인하기 위해서 jq --version 명령을 입력해줍니다.\n\n$ jq --version\n\n\n패키지가 제대로 설치되었다면 아래와 같이 jq 패키지의 버전이 표시되게 됩니다.\n\njq-1.6\n\n\n이제 본격적으로 jq를 이용해서 레포의 생성일을 확인할 차례입니다.\n\n$ curl https://api.github.com/repos/boyinblue/boyinblue.github.io | jq '.created_at'\n\n\n레포지토리의 생성일이 UTC(세계 협정시)를 기준으로 표기됩니다.\n\n\"2022-03-06T06:20:09Z\"\n\n\n실행 결과를 살펴보면 json 데이터 중에서 created_at 이라는 항목만 표시된 것을 알 수 있습니다. \ncrul 명령을 통해서 표준출력으로 튀어나오는 json 데이터를 다시 파이프를 통해서 jq에 공급해주는 명령입니다. \njq는 json 데이터중에서 created_at 항목만 추출해서 출력해줍니다.\n\n한가지 아쉬운 점은 결과값이 쌍따움표 안에 표기되어 있다는 것입니다. \n쌍다움표를 제거시키기 위해서 xargs 라는 명령을 사용하겠습니다.\n\n$ curl https://api.github.com/repos/boyinblue/boyinblue.github.io | jq '.created_at' | xargs\n\n\n위와 같이 수행하면 쌍따움표가 제거된 상태로 레포지토리의 생성일이 출력됩니다.\n\n2022-03-06T06:20:09Z\n\n\nxargs 명령을 거치면서 쌍따움표가 제거되어 원하는대로 깔끔하게 출력되었습니다.\n\n결론\n\n본 페이지에서는 GitHub Repoitory의 생성일을 확인하는 방법에 대해서 살펴보았습니다.\n\n이상입니다.\n"]
Title : Git server certificate verification failed. CAfile none CRLfile none 에러 조치 방법
URL : /001_github_api/003-server-certificate-verification-fail.html
Description : GitHub 서버로부터 통신을 시도할 때 server certificate verification failed. CAfile none CRLfile none 에러가 발생할 경우 조치하는 방법에 대해서 설명합니다.
Content : 필자는 초소형 컴퓨터인 라즈베리파이4B를 이용하여 본 웹페이지의 글을 작성하고 있다.
라즈베리파이4B를 웹서버로 사용하는 것은 아니고,
GitHub Pages라는 GitHub에서 제공하는 웹서비스를 이용해서 글들을 작성하고 있다.

오늘 아침 Ubuntu Linux를 업그레이드하고 재부팅을 했더니,
아래와 같은 메시지가 발생하면서 git에 접속을 할 수 없었다.

문제 상황

git pull 명령을 수행하려 하였으나, 아래와 같은 메시지가 발생하면서 수행되지 않음.


fatal: unable to access 'https://github.com/boyinblue/boyinblue.github.io.git/': server certificate verification failed. CAfile: none CRLfile: none


서버 인증서 검증에 실패했다는 이 메시지는 왜 발생을 했을까요?
결론부터 이야기하자면, 재부팅 이후에 라즈베리파이의 RTC 값이 약 2개월 전으로 돌아갔기 때문입니다.

문제 해결 방법 (현재 시간을 재설정)

문제를 해결하는 방법은 아주 간단합니다.
라즈베리파이의 현재 시간을 재설정해주면 됩니다.
라즈베리파이는 RTC 블럭을 제공하지만, RTC 값을 유지시켜주는 배터리가 없기 때문에,
재부팅시에 현재 시간 설정이 올바르지 못한 경우가 있습니다.
이 때문에 웹브라우저 접속이 안 되는 경우가 자주 발생합니다.

RTC 값을 수동으로 설정해주는 것으로 본 문제를 해결할 수는 있었지만,
이후에 재부팅될 경우 RTC 값이 맞지 않을 때마다 현재 시간을 매번 맞춰줘야 하는 것을 제법 성가신 일입니다.

아래 페이지에는 라즈베리파이의 현재 시간 값을 자동으로 가져오는 방법에 대한 내용이 기술되어 있습니다.






[라즈베리파이] 현재 시간 정보를 자동으로 가져와서 유지하는 방법
라즈베리파이는
현재 시간 정보를 유지하지 못합니다. 작고 저렴하지만 파워풀한 라즈베리파이에 RTC(Real Time Clock) 블록은 포함되어 있지 않습니다. 다시 말하면 라즈베리파이에는 현
재 시간 정보를 유지하는..









이상입니다.
["필자는 초소형 컴퓨터인 라즈베리파이4B를 이용하여 본 웹페이지의 글을 작성하고 있다. \n라즈베리파이4B를 웹서버로 사용하는 것은 아니고, \nGitHub Pages라는 GitHub에서 제공하는 웹서비스를 이용해서 글들을 작성하고 있다.\n\n오늘 아침 Ubuntu Linux를 업그레이드하고 재부팅을 했더니, \n아래와 같은 메시지가 발생하면서 git에 접속을 할 수 없었다.\n\n문제 상황\n\ngit pull 명령을 수행하려 하였으나, 아래와 같은 메시지가 발생하면서 수행되지 않음.\n\n\nfatal: unable to access 'https://github.com/boyinblue/boyinblue.github.io.git/': server certificate verification failed. CAfile: none CRLfile: none\n\n\n서버 인증서 검증에 실패했다는 이 메시지는 왜 발생을 했을까요? \n결론부터 이야기하자면, 재부팅 이후에 라즈베리파이의 RTC 값이 약 2개월 전으로 돌아갔기 때문입니다.\n\n문제 해결 방법 (현재 시간을 재설정)\n\n문제를 해결하는 방법은 아주 간단합니다. \n라즈베리파이의 현재 시간을 재설정해주면 됩니다. \n라즈베리파이는 RTC 블럭을 제공하지만, RTC 값을 유지시켜주는 배터리가 없기 때문에, \n재부팅시에 현재 시간 설정이 올바르지 못한 경우가 있습니다. \n이 때문에 웹브라우저 접속이 안 되는 경우가 자주 발생합니다.\n\nRTC 값을 수동으로 설정해주는 것으로 본 문제를 해결할 수는 있었지만, \n이후에 재부팅될 경우 RTC 값이 맞지 않을 때마다 현재 시간을 매번 맞춰줘야 하는 것을 제법 성가신 일입니다.\n\n아래 페이지에는 라즈베리파이의 현재 시간 값을 자동으로 가져오는 방법에 대한 내용이 기술되어 있습니다.\n\n\n\n\n \n \n [라즈베리파이] 현재 시간 정보를 자동으로 가져와서 유지하는 방법\n 라즈베리파이는\n 현재 시간 정보를 유지하지 못합니다. 작고 저렴하지만 파워풀한 라즈베리파이에 RTC(Real Time Clock) 블록은 포함되어 있지 않습니다. 다시 말하면 라즈베리파이에는 현\n재 시간 정보를 유지하는..\n \n \n \n \n \n \n\n\n\n이상입니다.\n"]
Title : Ubuntu Linux Crontab 실행 안됨 (crontab에서는 bash 문법 허용 안됨)
URL : /008_ubuntu/003-ubuntu-crontab-does-not-work.html
Description : 우분투 리눅스에서 crontabl이 실행되지 않는 문제 해결 방법에 대해서 설명합니다.
Content : 리눅스에서 주기적으로 어떤 동작이나 작업을 수행시키고 싶을 때
우리는 crontab을 사용합니다.
bash 쉘에서는 잘 동작하던 스크립트가 crontab에만 등록하면
제대로 동작하지 않아서 애를 먹었던 적이 있었습니다.
쉘에서는 잘 동작하는데 crontab에서는 동작하지 않으면 많이 답답하더군요.

결론부터 말씀드리자면, bash 쉘에서의 문법이 crontab에서는 지원되지 않아서 발생한는 문제가 많습니다.
본 페이지에서는 쉘에서는 잘 동작하는 스크립트가 crontab에 등록하면 동작하지 않는 문제에 대해서 살펴보고 기록합니다.

crontab에 pushd 명령과 popd 명령을 사용해서는 안됨

기본적으로 Ubuntu Linux에서 터미널을 열면 쉘이 실행됩니다.
대부분은 bash 쉘을 사용하지요.
그래서 crontab에 등록할때도 아래와 같이 입력하는 실수를 범할 수 있습니다.

15 * * * * pushd ~/project/crontab/boyinblue.github.io/build;./auto.sh ;popd
45 * * * * pushd ~/project/crontab/blog_automation;./auto.sh ;popd
30 * * * * pushd ~/project/crontab/raspberry/get_public_ip;./get_public_ip.sh;popd


사실 이게 실수라는 것을 인지하기는 쉽지 않습니다.
SW 개발자로 일하면서 간혹 문제점을 야기하는데
한 가지 원인은 어이없는 실수이고,
나머지 원인은 무지에서 비롯된 것이 많습니다.

이 경우는 무지에서 비롯된 문제입니다.
왜냐하면 pushd 명령과 popd 명령은 bash 쉘에서만 사용할 수 있는 문법으로,
crontab에서는 이를 인식할 수 없기 때문입니다.

위의 명령을 아래와 같이 수정하면 깔끔하게 해결됩니다.

15 * * * * cd ~/project/crontab/boyinblue.github.io/build; ./auto.sh
45 * * * * cd ~/project/crontab/blog_automation; ./auto.sh
30 * * * * cd ~/project/crontab/raspberry/get_public_ip; ./get_public_ip.sh


pushd 명령을 cd로 변경하면 그 이후부터는 의도한대로 동작하는 것을 확인할 수 있습니다.

crontab이 제대로 동작하지 않을 때 원인 분석 방법

위의 문제는 한 가지 예시에 불과합니다.
지원하지 않는 pushd 명령을 사용하는 것 외에도 다양한 원인들이 있을 수 있겠지요.
첫 단계로 시도해볼 수 있는 것은 로그를 수집하는 것입니다.
하지만 이것은 좋은 방식이면서도 좋지 않은 방식입니다.

아래와 같이 crontab 실행시에 로그를 남기도록 하는 시도는 제대로 동작하지 않을 수 있습니다.

0 * * * * pushd abc >> /tmp/error.txt ; ./a.out >> /tmp/error.txt


위와 같이 수행 결과를 로그로 남기는 것도 가능합니다만,
표준 출력만 파일에 기록되기 때문에 표준 에러는 로그 파일에 기록되지 않지요.

한 줄로 입력하는 crontab에 로그를 남기는 동작까지 넣는다는 것은 아주 성가신 일이겠지요.
그래서 발견한 깔끔한 방법이 있습니다.

그것은 바로 crontab의 수행 결과를 이메일로 수신하는 것입니다.

crontab 수행시 문제가 발생할 경우 이메일로 수신하는 방법

PC에 SMTP 설정을 해두면 crontab 수행시에 에러가 발생할 경우 이메일로 자동 리포팅 됩니다.
제가 crontab에서 pushd 명령을 사용해서 문제가 되었을 것을 찾게된 것도
해당 로그가 이메일로 전송되었기 때문에 알 수 있었던 것입니다.

root
오전 10:00 (29분 전)
/bin/sh: 1: pushd: not found /bin/sh: 1: ./auto.sh: not found /bin/sh: 1: popd: not found


위와 같이 pushd 명령이 not found 에러를 리턴하면서 실패를 했고,
당연히 경로가 맞지 않아서 그 뒤의 명령들이 줄줄이 실패되는 악순환이 발생했지요.

SMTP 설정을 통해서 crontab 실패시의 로그를 수신하는 방법

그렇다면 crontab 실패시의 로그를 이메일로 수신하게 하려면 어떻게 해야 할까요?
ssmtp 패키지를 설치하고 SMTP 설정을 해주면 됩니다.

관련된 내용은 아래의 제 글을 참고하시기 바랍니다.

Ubuntu Linux에서 ssmtp로 이메일 전송하는 초간단 방법

결론

본 페이지에서는 crontab에서 지원되지 않는 pushd 명령 때문에 crontab이 제대로 수행되지 않은 문제에 대해서 살펴보았습니다.

또한, crontab이 수행되지 않을 때 문제의 원인을 파악하기 위해서는 SMTP 설정을 해주면 쉽게 원인을 파악할 수 있다는 것에 대해서도 언급하였습니다.

이상입니다.
["리눅스에서 주기적으로 어떤 동작이나 작업을 수행시키고 싶을 때 \n우리는 crontab을 사용합니다. \nbash 쉘에서는 잘 동작하던 스크립트가 crontab에만 등록하면 \n제대로 동작하지 않아서 애를 먹었던 적이 있었습니다. \n쉘에서는 잘 동작하는데 crontab에서는 동작하지 않으면 많이 답답하더군요.\n\n결론부터 말씀드리자면, bash 쉘에서의 문법이 crontab에서는 지원되지 않아서 발생한는 문제가 많습니다. \n본 페이지에서는 쉘에서는 잘 동작하는 스크립트가 crontab에 등록하면 동작하지 않는 문제에 대해서 살펴보고 기록합니다.\n\ncrontab에 pushd 명령과 popd 명령을 사용해서는 안됨\n\n기본적으로 Ubuntu Linux에서 터미널을 열면 쉘이 실행됩니다. \n대부분은 bash 쉘을 사용하지요. \n그래서 crontab에 등록할때도 아래와 같이 입력하는 실수를 범할 수 있습니다.\n\n15 * * * * pushd ~/project/crontab/boyinblue.github.io/build;./auto.sh ;popd\n45 * * * * pushd ~/project/crontab/blog_automation;./auto.sh ;popd\n30 * * * * pushd ~/project/crontab/raspberry/get_public_ip;./get_public_ip.sh;popd\n\n\n사실 이게 실수라는 것을 인지하기는 쉽지 않습니다. \nSW 개발자로 일하면서 간혹 문제점을 야기하는데 \n한 가지 원인은 어이없는 실수이고, \n나머지 원인은 무지에서 비롯된 것이 많습니다.\n\n이 경우는 무지에서 비롯된 문제입니다. \n왜냐하면 pushd 명령과 popd 명령은 bash 쉘에서만 사용할 수 있는 문법으로, \ncrontab에서는 이를 인식할 수 없기 때문입니다.\n\n위의 명령을 아래와 같이 수정하면 깔끔하게 해결됩니다.\n\n15 * * * * cd ~/project/crontab/boyinblue.github.io/build; ./auto.sh\n45 * * * * cd ~/project/crontab/blog_automation; ./auto.sh\n30 * * * * cd ~/project/crontab/raspberry/get_public_ip; ./get_public_ip.sh\n\n\npushd 명령을 cd로 변경하면 그 이후부터는 의도한대로 동작하는 것을 확인할 수 있습니다.\n\ncrontab이 제대로 동작하지 않을 때 원인 분석 방법\n\n위의 문제는 한 가지 예시에 불과합니다. \n지원하지 않는 pushd 명령을 사용하는 것 외에도 다양한 원인들이 있을 수 있겠지요. \n첫 단계로 시도해볼 수 있는 것은 로그를 수집하는 것입니다. \n하지만 이것은 좋은 방식이면서도 좋지 않은 방식입니다.\n\n아래와 같이 crontab 실행시에 로그를 남기도록 하는 시도는 제대로 동작하지 않을 수 있습니다.\n\n0 * * * * pushd abc >> /tmp/error.txt ; ./a.out >> /tmp/error.txt\n\n\n위와 같이 수행 결과를 로그로 남기는 것도 가능합니다만, \n표준 출력만 파일에 기록되기 때문에 표준 에러는 로그 파일에 기록되지 않지요.\n\n한 줄로 입력하는 crontab에 로그를 남기는 동작까지 넣는다는 것은 아주 성가신 일이겠지요. \n그래서 발견한 깔끔한 방법이 있습니다.\n\n그것은 바로 crontab의 수행 결과를 이메일로 수신하는 것입니다.\n\ncrontab 수행시 문제가 발생할 경우 이메일로 수신하는 방법\n\nPC에 SMTP 설정을 해두면 crontab 수행시에 에러가 발생할 경우 이메일로 자동 리포팅 됩니다. \n제가 crontab에서 pushd 명령을 사용해서 문제가 되었을 것을 찾게된 것도 \n해당 로그가 이메일로 전송되었기 때문에 알 수 있었던 것입니다.\n\nroot\n오전 10:00 (29분 전)\n/bin/sh: 1: pushd: not found /bin/sh: 1: ./auto.sh: not found /bin/sh: 1: popd: not found\n\n\n위와 같이 pushd 명령이 not found 에러를 리턴하면서 실패를 했고, \n당연히 경로가 맞지 않아서 그 뒤의 명령들이 줄줄이 실패되는 악순환이 발생했지요.\n\nSMTP 설정을 통해서 crontab 실패시의 로그를 수신하는 방법\n\n그렇다면 crontab 실패시의 로그를 이메일로 수신하게 하려면 어떻게 해야 할까요? \nssmtp 패키지를 설치하고 SMTP 설정을 해주면 됩니다.\n\n관련된 내용은 아래의 제 글을 참고하시기 바랍니다.\n\nUbuntu Linux에서 ssmtp로 이메일 전송하는 초간단 방법\n\n결론\n\n본 페이지에서는 crontab에서 지원되지 않는 pushd 명령 때문에 crontab이 제대로 수행되지 않은 문제에 대해서 살펴보았습니다.\n\n또한, crontab이 수행되지 않을 때 문제의 원인을 파악하기 위해서는 SMTP 설정을 해주면 쉽게 원인을 파악할 수 있다는 것에 대해서도 언급하였습니다.\n\n이상입니다.\n"]
Title : 공인 IP를 확인하는 방법(Windows, Ubuntu Linux 공통)
URL : /008_ubuntu/002.html
Description : Ubuntu Linux 쉘에서 공인 IP를 확인하는 방법을 설명합니다.
Content : 네트워크에 대해서 잘 모르는 학부생 시절에 사설IP와 공인IP의 차이점에 대해서 잘 알지 못했다.
학부생 시절 여름방학에 게임을 만드는 한 업체에서 현장실습을 할 기회가 있었는데,
거기에서 공인IP와 사설IP의 차이점에 대해서 알 수 있었다.

2000년 초반이었을 그 당시 그 게임 업체에서는 네트워크 게임을 개발 중이었는데,
사설 IP를 이용해서 통신을 하다보니 제대로 접속이 되지 않는 문제로 많은 어려움을 겪었었나보다.
지금이야 공인IP와 사설IP의 개념을 많은 사람들이 알고 있지만,
그 당시에는 제법 고생하고 힘들게 알아냈던 정보였는지,
현장 실습 인턴직이었던 나에게 공인IP와 사설IP에 대한 개념이 잘 정리된 문서를
나에게 보여줬다.

공인IP와 사설IP의 차이

공인IP(Public IP)라는 것은 전 세계에 주소가 단 하나뿐민 IP이다.
해당 IP가 인터넷에 연결되어 있으면, 전 세계 어디서든 그 IP를 찾아낼 수 있다.

IP 주소는 한정되어 있으므로 요즘에는 공인IP의 부족 사태를 겪고 있다.
그래서 대안으로 나온 것이 IPV6이다.

반면, 사설IP(Private IP)는 IP 대역 중에 일부를 사설 IP로 사용할 수 있도록 하였다.
공인IP 하나에 인터넷 공유기를 연결하면 PC, 스마트폰 등의 단말기를 다양하게 사용할 수 있다. 이 때 사용하는 것이 바로, 사설 IP 대역이다.
A, B, C 클래스의 일부를 사설 IP 대역으로 정해두었다.
대표적으로 많이 쓰이는 대역은 B클래스의 192.168.0.0 ~ 192.168.255.255 대역이다.

사설 IP는 당연히 중복될 수 있으며, 당연히 인터넷에서 라우팅이 불가능하다.
그렇기 때문에 사설 IP를 가진 단말기가 인터넷에 접속하여 통신을 하기 위해서는
공인 IP를 달고 통신을 해야 한다.

공인IP를 확인하는 방법

컴퓨터의 IP를 확인하는 방법은 아주 간단하다.
윈도우즈 PC의 경우는 ipconfig 명령을 실행해보면 된다.
리눅스 PC는 ifconfig 명령을 실행해보면 된다.

만약 리눅스 PC에서 ifconfig를 입력했을 때 IP가 표시되지 않는다면,
아래의 명령으로 net-tools 패키지를 설치하면 된다.

$ sudo apt-get install ifconfig


아마 대부분의 경우는 사설 IP 대역일 것이다.
공인 IP를 바로 사용하는 회사, 학교 등을 제외하고는 사설 IP일 가능성이 아주 높다.
만약, 가정에서 인터넷 공유기를 사용하지 않고 하나의 인터넷 회선을 바로 단말기에 연결해서 사용하는 경우라면 공인IP일 가능성이 높겠다.

사설 IP가 할당된 단말기인데 공인IP를 어떻게 알 수 있을까?
만약 인터넷 공유기를 사용하고 있다면, 인터넷 공유기 셋업 페이지에 접속해서 알아볼 수 있는 방법이 있다.
대부분 게이트웨이 주소로 접속해보면 인터넷 공유기의 셋업 페이지에 접속할 수 있다.
간혹 8080 포트로 접속해야 하는 경우도 있지만 대부분 큰 어려움 없이 접속해서 확인해볼 수 있다.

공인IP를 확인하는 명령어

그럼 지금부터 공인IP를 확인하는 방법에 대해서 설명하겠다.
인터넷 공유기에 접속하거나 그런 귀찮은 작업이 전혀 없이,
오직 명령어 하나만 쉘에 입력하면 된다.

$ curl ifconfig.me

위와 같이 입력하면 공인 IP 주소가 즉각적으로 떡하니 나온다.

106.101.2.243


curl 명령은 리눅스와 윈도우즈 모두 사용할 수 있으므로 공통적으로 사용할 수 있다.
만약, curl 패키지가 설치되어 있지 않으면 Ubuntu Linux 기준으로 아래의 명령을 입력하면 된다.

$ sudo apt-get install curl


“curl ifconfig.me” 명령의 비밀!

curl 명령어는 인터넷에서 파일을 다운로드 받거나 받은 내용을 출력해주는 명령어다.
그런 명령어에 ifconfig.me를 입력하면 공인IP를 알아낼 수 있는 옵션이 동작하는 것처럼 보일 수 있으나, 실제로는 그렇지 않다.

curl 명령이 아니라 wget 명령으로도 공인IP를 알아낼 수 있다.

wget ifconfig.me
cat index.html


눈치를 채셨는가?
“ifconfig.me” 라는 것은 옵션이 아니올시다.
웹서버 주소인 것이다.

즉, $ curl ifconfig.me라는 명령은 아래의 명령과 equivalent 하다.

$ curl http://ifconfig.me
$ curl https://ifconfig.me


그렇다. ifconfi.me는 웹서버 주소이기 때문에 웹서버에서 내 PC의 공인IP를 알려주는 것이다.
웹 서버라는 것은 당연히 요청에 대한 응답을 제공해줘야 하는데,
그럴려면 단말기의 공인 IP를 알고 있어야 한다.

웹 브라우저로 열어보면 훨씬 더 많은 내용을 확인할 수 있다.



웹 페이지를 살펴보면 공인IP 외에도 더 많은 정보를 읽어올 수 있는 URL들을 제공한다.


curl ifconfig.me : 공인IP를 받아 온다.
curl ifconfig.me/ip : 위와 같은 동작이다.
curl ifconfig.me/ua : 브라우저 정보를 읽어올 수 있다.
curl ifconfig.me/lang : 단말기의 언어를 알 수 있다.
curl ifconfig.me/mime : MIME 정보를 읽어올 수 있다.
curl ifconfig.me/forwarded
curl ifconfig.me/all : 모든 정보를 받아올 수 있다.
curl ifconfig.me/all.json : 모든 정보를 json 포맷으로 받아올 수 있다.


비슷한 서비스를 제공하는 웹서버(ifconfig.io)

비슷한 서비스를 제공하는 웹서버가 또 있다.
바로 “https://ifconfig.io”이다.
사용법은 ifconfig.if와 동일하다.
쉘에서 아래와 같이 입력해주면 된다.

$ curl ifconfig.io


결론

본 페이지에서 우리는 공인IP의 개념과 사설IP의 개념에 대해서 알아보았고,
공인IP를 손쉽게 확인할 수 있는 방법에 대해서도 다뤄보았다.
그리고 그 명령어의 의미가 어떻게 되는지에 대해서도 확인해보았다.
비밀은, 공인IP를 알려주는 웹서버에 있었다.
["네트워크에 대해서 잘 모르는 학부생 시절에 사설IP와 공인IP의 차이점에 대해서 잘 알지 못했다. \n학부생 시절 여름방학에 게임을 만드는 한 업체에서 현장실습을 할 기회가 있었는데, \n거기에서 공인IP와 사설IP의 차이점에 대해서 알 수 있었다.\n\n2000년 초반이었을 그 당시 그 게임 업체에서는 네트워크 게임을 개발 중이었는데, \n사설 IP를 이용해서 통신을 하다보니 제대로 접속이 되지 않는 문제로 많은 어려움을 겪었었나보다. \n지금이야 공인IP와 사설IP의 개념을 많은 사람들이 알고 있지만, \n그 당시에는 제법 고생하고 힘들게 알아냈던 정보였는지, \n현장 실습 인턴직이었던 나에게 공인IP와 사설IP에 대한 개념이 잘 정리된 문서를 \n나에게 보여줬다.\n\n공인IP와 사설IP의 차이\n\n공인IP(Public IP)라는 것은 전 세계에 주소가 단 하나뿐민 IP이다. \n해당 IP가 인터넷에 연결되어 있으면, 전 세계 어디서든 그 IP를 찾아낼 수 있다.\n\nIP 주소는 한정되어 있으므로 요즘에는 공인IP의 부족 사태를 겪고 있다. \n그래서 대안으로 나온 것이 IPV6이다.\n\n반면, 사설IP(Private IP)는 IP 대역 중에 일부를 사설 IP로 사용할 수 있도록 하였다. \n공인IP 하나에 인터넷 공유기를 연결하면 PC, 스마트폰 등의 단말기를 다양하게 사용할 수 있다. 이 때 사용하는 것이 바로, 사설 IP 대역이다. \nA, B, C 클래스의 일부를 사설 IP 대역으로 정해두었다. \n대표적으로 많이 쓰이는 대역은 B클래스의 192.168.0.0 ~ 192.168.255.255 대역이다.\n\n사설 IP는 당연히 중복될 수 있으며, 당연히 인터넷에서 라우팅이 불가능하다. \n그렇기 때문에 사설 IP를 가진 단말기가 인터넷에 접속하여 통신을 하기 위해서는 \n공인 IP를 달고 통신을 해야 한다.\n\n공인IP를 확인하는 방법\n\n컴퓨터의 IP를 확인하는 방법은 아주 간단하다. \n윈도우즈 PC의 경우는 ipconfig 명령을 실행해보면 된다. \n리눅스 PC는 ifconfig 명령을 실행해보면 된다.\n\n만약 리눅스 PC에서 ifconfig를 입력했을 때 IP가 표시되지 않는다면, \n아래의 명령으로 net-tools 패키지를 설치하면 된다.\n\n$ sudo apt-get install ifconfig\n\n\n아마 대부분의 경우는 사설 IP 대역일 것이다. \n공인 IP를 바로 사용하는 회사, 학교 등을 제외하고는 사설 IP일 가능성이 아주 높다. \n만약, 가정에서 인터넷 공유기를 사용하지 않고 하나의 인터넷 회선을 바로 단말기에 연결해서 사용하는 경우라면 공인IP일 가능성이 높겠다.\n\n사설 IP가 할당된 단말기인데 공인IP를 어떻게 알 수 있을까? \n만약 인터넷 공유기를 사용하고 있다면, 인터넷 공유기 셋업 페이지에 접속해서 알아볼 수 있는 방법이 있다. \n대부분 게이트웨이 주소로 접속해보면 인터넷 공유기의 셋업 페이지에 접속할 수 있다. \n간혹 8080 포트로 접속해야 하는 경우도 있지만 대부분 큰 어려움 없이 접속해서 확인해볼 수 있다.\n\n공인IP를 확인하는 명령어\n\n그럼 지금부터 공인IP를 확인하는 방법에 대해서 설명하겠다. \n인터넷 공유기에 접속하거나 그런 귀찮은 작업이 전혀 없이, \n오직 명령어 하나만 쉘에 입력하면 된다.\n\n $ curl ifconfig.me \n\n위와 같이 입력하면 공인 IP 주소가 즉각적으로 떡하니 나온다.\n\n106.101.2.243\n\n\ncurl 명령은 리눅스와 윈도우즈 모두 사용할 수 있으므로 공통적으로 사용할 수 있다. \n만약, curl 패키지가 설치되어 있지 않으면 Ubuntu Linux 기준으로 아래의 명령을 입력하면 된다.\n\n$ sudo apt-get install curl\n\n\n“curl ifconfig.me” 명령의 비밀!\n\ncurl 명령어는 인터넷에서 파일을 다운로드 받거나 받은 내용을 출력해주는 명령어다. \n그런 명령어에 ifconfig.me를 입력하면 공인IP를 알아낼 수 있는 옵션이 동작하는 것처럼 보일 수 있으나, 실제로는 그렇지 않다.\n\ncurl 명령이 아니라 wget 명령으로도 공인IP를 알아낼 수 있다.\n\nwget ifconfig.me\ncat index.html\n\n\n눈치를 채셨는가? \n“ifconfig.me” 라는 것은 옵션이 아니올시다. \n웹서버 주소인 것이다.\n\n즉, $ curl ifconfig.me라는 명령은 아래의 명령과 equivalent 하다.\n\n$ curl http://ifconfig.me\n$ curl https://ifconfig.me\n\n\n그렇다. ifconfi.me는 웹서버 주소이기 때문에 웹서버에서 내 PC의 공인IP를 알려주는 것이다. \n웹 서버라는 것은 당연히 요청에 대한 응답을 제공해줘야 하는데, \n그럴려면 단말기의 공인 IP를 알고 있어야 한다.\n\n웹 브라우저로 열어보면 훨씬 더 많은 내용을 확인할 수 있다.\n\n\n\n웹 페이지를 살펴보면 공인IP 외에도 더 많은 정보를 읽어올 수 있는 URL들을 제공한다.\n\n\n curl ifconfig.me : 공인IP를 받아 온다.\n curl ifconfig.me/ip : 위와 같은 동작이다.\n curl ifconfig.me/ua : 브라우저 정보를 읽어올 수 있다.\n curl ifconfig.me/lang : 단말기의 언어를 알 수 있다.\n curl ifconfig.me/mime : MIME 정보를 읽어올 수 있다.\n curl ifconfig.me/forwarded \n curl ifconfig.me/all : 모든 정보를 받아올 수 있다.\n curl ifconfig.me/all.json : 모든 정보를 json 포맷으로 받아올 수 있다.\n\n\n비슷한 서비스를 제공하는 웹서버(ifconfig.io)\n\n비슷한 서비스를 제공하는 웹서버가 또 있다. \n바로 “https://ifconfig.io”이다. \n사용법은 ifconfig.if와 동일하다. \n쉘에서 아래와 같이 입력해주면 된다.\n\n$ curl ifconfig.io\n\n\n결론\n\n본 페이지에서 우리는 공인IP의 개념과 사설IP의 개념에 대해서 알아보았고, \n공인IP를 손쉽게 확인할 수 있는 방법에 대해서도 다뤄보았다. \n그리고 그 명령어의 의미가 어떻게 되는지에 대해서도 확인해보았다. \n비밀은, 공인IP를 알려주는 웹서버에 있었다.\n"]
Title : Ubuntu Linux에서 ssmtp로 이메일 전송하는 초간단 방법 (이메일 전송 자동화)
URL : /008_ubuntu/001.html
Description : ssmtp 패키지를 이용하여 이메일을 전송하는 방법에 대해서 설명합니다.
Content : 많은 개발자들이 오해하고 있는 것이 있다.
리눅스에서 메일을 송신하려면 SMTP 서버를 구축해야 되는지 말이다.
구글에서 “Ubuntu 리눅스에서 메일을 보내는 방법”을 검색해보면 SMTP부터 구성하도록 작성된 글들이 많다.
절대 그럴 필요 없다. 이 글이 여러분들의 시간과 노력을 절약해주기를 바란다.

물론, 썬더버드(ThunderBird)와 같은 GUI 기반의 메일 송수신 프로그램을 제공하지만,
그런 기본적인 내용을 다루는 글이라면 이 글을 시작하지도 않았을 것이다.

이메일 전송 자동화를 이루려면 ssmtp처럼 쉘 명령으로 이메일을 전송할 수 있는 기능이 구현되어야 하기 때문이다.
본 페이지에서는 ssmtp라는 프로그램으로 쉘에서 메일을 보낼 수 있는 방법을 소개한다.

ssmtp 메일 전송 프로그램 소개

Ubuntu Linux에서는 ssmtp 프로그램을 이용하면 손쉽게 메일을 보낼 수 있다.
SMTP 서버를 구성할 필요가 없고, gmail과 같은 메일 서비스를 그대로 이용할 수 있다.
ssmtp라는 패키지를 설치하고 설정을 해주면 큰 어려움 없이 쉘 명령으로 메일을 전송할 수 있다.

ssmtp의 가장 큰 단점이라면 첨부 파일을 보낼 수 없다는 것이다.
만약 첨부파일 전송이 필요하다면 다른 종류의 메일 송신 프로그램을 사용하시기를 바란다.

ssmtp 사용 방법

ssmtp로 메일을 송신하기 위해서는 아래와 같이 3단계가 필요하다.


ssmtp 패키지를 설치해야 한다.
ssmtp 환경 설정이 필요하다.
형식에 맞는 메일 내용을 작성한 후에 ssmtp를 실행하면 된다.


ssmtp 패키지가 설치되어 있는지 확인하는 방법

ssmtp 패키지를 설치하는 방법을 설명하기에 앞서,
ssmtp 패키지가 설치되어 있는지부터 먼저 확인해보겠다.
쉘에서 아래 명령을 실행하고 그 결과를 확인해보자.

$ ssmtp --version


만약 ssmtp가 설치되어 있다면 아래와 같은 결과가 나온다.

ssmtp: No recipients supplied - mail will not be sent


만약 아래와 같은 결과가 나오면 ssmtp가 설치되어 있지 않으므로 설치해야 한다.

명령어 'ssmtp' 을(를) 찾을 수 없습니다. 그러나 다음을 통해 설치할 수 있습니다:
sudo apt install ssmtp


친절하게도 ssmtp를 사용하기 위해서는 설치해야하는 패키지까지 알려준다.

ssmtp 패키지 설치 방법

ssmtp 패키지 설치하는 방법은 아주 간단하다.
키를 추가하거나 소스 리스트를 추가해줄 필요도 없다.
그저 쉘에서 아래 명령만 수행해주면 된다.

$ sudo apt-get install ssmtp


ssmtp 환경 설정 방법 (gmail 기준)

그렇다면 지금부터는 gmail 기준으로 ssmtp 환경 설정하는 방법에 대해서 설명하겠다.
결론부터 이야기하자면 아래와 같이 설정하면 된다.

$ sudo vi /etc/ssmtp/ssmtp.conf


선호하는 편집기로 /etc/ssmtp/ssmtp.conf 설정 파일을 편집한다.

아래와 같이 설정한다.

root=yourmail@gmail.com
mailhub=smtp.gmail.com:587
FromLineOverride=YES
UseSTARTTLS=YES
UseTSL=YES
AuthUser=yourmail
AuthPass=app password (16자리 문자)


여기에서 주의할 것이 있다.
AuthPass에 비밀번호를 입력하면 될 것 같지만, 실제로는 토큰을 입력해야 한다.
앱 비밀번호를 입력해야 하는데, 이것은 계정 비밀 번호와는 다르다.

관련 내용은 아래 사이트에 접속하면 앱 비밀번호 설정 방법에 대해서 확인할 수 있다.

gmail 앱 비밀번호 로그인

ssmtp로 간단하게 메일을 전송하는 방법

선호하는 편집기를 통해서 보낼 메일의 내용을 입력하면 된다.
ssmtp로 메일을 보내기 위해서는 정해진 포맷의 헤더를 포함해야 한다.


To: boyinblue@hanmail.net
From: boyinblue: boyinblue@naver.com
MIME-Version: 1.0
Content-Type: text/html; charset=utf-8
Subject: This is a test mail
This is a test message.


위와 같이 메일을 작성했다면 아래와 같이 명령어 한 줄로 메일을 전송할 수 있다.

cat email.txt | ssmtp -v -t



[<-] 220 smtp.gmail.com ESMTP **************************** - gsmtp
[->] EHLO parksejin-desktop
[<-] 250 SMTPUTF8
[->] STARTTLS
[<-] 220 2.0.0 Ready to start TLS
[->] EHLO parksejin-desktop
[<-] 250 SMTPUTF8
[->] AUTH LOGIN
[<-] 334 ******
[->] ******
[<-] 334 ******
[<-] 235 2.7.0 Accepted
[->] MAIL FROM:<boyinblue: esregnet0409@gmail.com>
[<-] 250 2.1.0 OK ******* - gsmtp
[->] RCPT TO:<boyinblue@hanmail.net>
[<-] 250 2.1.5 OK ******** - gsmtp
[->] DATA
[<-] 354 Go ahead *********** - gsmtp
[->] Received: by parksejin-desktop (sSMTP sendmail emulation); Fri, 18 Mar 2022 11:13:52 +0900
[->] Date: Fri, 18 Mar 2022 11:13:52 +0900
[->] To: boyinblue@hanmail.net
[->] From: boyinblue: esregnet0409@gmail.com
[->] MIME-Version: 1.0
[->] Content-Type: text/html; charset=utf-8
[->] Subject: This is a test mail
[->] This is a test message.
[->]
[->] .
[<-] 250 2.0.0 OK ******* - gsmtp
[->] QUIT
[<-] 221 2.0.0 closing connection ***** - gsmtp


“ssmtp: Cannot open mail:25” 에러 발생시

만약 ssmtp: Cannot open mail:25라는 에러가 발생한다면,
SMTP 서버 설정이 올바르지 않을 가능성이 있다.
/etc/ssmtp/ssmtp.conf 파일을 열어서 mailhub 설정이 올바른지 확인해본다.

$ sudo vi /etc/ssmtp/ssmtp.conf


/etc/ssmtp/ssmtp.conf 파일의 퍼미션은 0640이다.
따라서 편집을 위해서는 root 권한이 필요하다.
혹시라도 mailhub=mail 로 되어 있으면 mailhub에 SMTP 서버 주소를 기입한다.

mailhub=mail 부분을 mailhub=smtp.gmail.com로 변경해준다.

필자의 경우는 gmail을 예로 입력했지만, 그 외의 다른 SMTP 주소를 사용하면 된다.

/etc/ssmtp/ssmtp.conf 파일을 편집하려고 하였으나 내용이 비어있을 경우

만약 vi /etc/ssmtp/ssmtp.conf 명령으로 파일 편집을 시도했는데,
파일 내용이 완전히 비어있다면 퍼미션 문제이다.

$ sudo ls -all /etc/ssmtp/ssmtp.conf


sudo ls -all /etc/ssmtp/ssmtp.conf 명령으로 해당 파일의 퍼미션을 삺펴보면 0640으로 되어 있는 것을 알 수 있다.

-rw-r----- 1 root mail 598 3월 17 16:43 /etc/ssmtp/ssmtp.conf


즉, root만이 해당 파일을 편집할 수 있고, 읽기 권한은 mail 그룹만 가능하다.
이 때는 sudo 명령을 통해서 root 권한으로 편집을 시도하면 된다.

sudo vi /etc/ssmtp/ssmtp.conf 와 같이 sudo 명령으로 파일 편집기를 열었는지 다시 확인해보자.

“Must issue a STARTTLS command first” 에러 발생시

위와 같은 에러가 발생한다면 ssmtp.conf 파일을 열어서 UseSTARTTLS=YES와 같이 UseSTARTTLS 설정을 해주면 된다.

root=esregnet0409@gmail.com
hostname=esregenet0409@gmail.com
FromLineOverride=YES


“ssmtp: Authorization failed (535 5.7.8)” 에러가 발생할 경우

아래와 같이 Authorization failed 에러가 발생했다면 앱 비밀번호가 올바르지 않다는 것이다.
앞서 언급했듯이 AuthPass는 비밀번호가 아니라 앱 비밀번호이다.

ssmtp: Authorization failed (535 5.7.8 https://support.google.com/mail/?p=BadCredentials j11-20020a63230b000000b00372a08b584asm6297113pgj.47 - gsmtp)


이 때는 앱 비밀번호를 발급받아서 AuthPass에 넣어주면 된다.
앱 비밀번호는 16자리짜리 문자열이다.

“도메인을 찾지 못하여 메일 전송이 안 되는 경우”

다음과 같은 DNS 오류가 발생한다면 hostname을 체크해보는게 좋다.

주소를 찾을 수 없음

도메인을 찾지 못하여 abc@abc.com 주소로 메일을 전송하지 못했습니다.
오타나 불필요한 공백이 있는지 확인한 후 다시 시도하세요.

응답은 다음과 같습니다.

DNS Error: DNS type 'mx' lookup of 'hostname' responded with code NXDOMAIN Domain name not found


이 때는 ssmtp.conf 설정 파일의 hostname을 체크해보시기 바란다.
필자의 경우는 gmail 계정으로 ssmtp를 설정했고,
hostname을 gmail의 smtp 서버 주소로 변경했더니 깔끔하게 문제가 해결되었다.

기존에 잘못 입력된 hostname

hostname=desktop


아래와 같이 hostname에 이메일의 smtp 주소를 입력해주면 된다.

hostname=smtp.gmail.com:587


gmail 서비스에서 전송할 수 있는 할당량을 초과할 경우

아래와 같은 메시지가 발생하면서 메일이 전송되지 않는다면
메일을 전송할 수 있는 할당량을 초과한 것이다.

ssmtp: 550 5.4.5 Daily user sending quota exceeded. - gsmtp


gmail에서는 메일을 전송할 수 있는 할당량이 있다.
Gmail for Developers 문서

해당 문제는 일정 시간이 지나면 자동적으로 해결된다.
참고로 특정 날짜 1일간에 보낼 수 있는 메일 개수가 제한된 것이 아니고,
Average Moving 방식으로 쿼터제를 시행한다.
혹시나 이런 문제가 자주 발생한다면 반복적으로 메일 발송을 과도하게 요청하고 있는것은 아닌지 체크하는게 좋다.

dead.letter라는 파일이 생성되어서 파일 크기가 점점 커짐

메일이 제대로 전송되지 못했을 경우
dead.letter 파일에 전송되지 못한 메일 데이터가 계속 쌓이게 된다.
메일 발송이 정말 중요해서 꼭 전달될 필요가 없다면 그냥 삭제하기를 권한다.

dead.letter 파일 정체

결론

이것으로 Ubuntu Linux에서 ssmtp 프로그램을 이용해서 메일을 전송하는 방법에 대한 설명을 모두 마친다.
["많은 개발자들이 오해하고 있는 것이 있다. \n리눅스에서 메일을 송신하려면 SMTP 서버를 구축해야 되는지 말이다. \n구글에서 “Ubuntu 리눅스에서 메일을 보내는 방법”을 검색해보면 SMTP부터 구성하도록 작성된 글들이 많다. \n절대 그럴 필요 없다. 이 글이 여러분들의 시간과 노력을 절약해주기를 바란다.\n\n물론, 썬더버드(ThunderBird)와 같은 GUI 기반의 메일 송수신 프로그램을 제공하지만, \n그런 기본적인 내용을 다루는 글이라면 이 글을 시작하지도 않았을 것이다.\n\n이메일 전송 자동화를 이루려면 ssmtp처럼 쉘 명령으로 이메일을 전송할 수 있는 기능이 구현되어야 하기 때문이다. \n본 페이지에서는 ssmtp라는 프로그램으로 쉘에서 메일을 보낼 수 있는 방법을 소개한다.\n\nssmtp 메일 전송 프로그램 소개\n\nUbuntu Linux에서는 ssmtp 프로그램을 이용하면 손쉽게 메일을 보낼 수 있다. \nSMTP 서버를 구성할 필요가 없고, gmail과 같은 메일 서비스를 그대로 이용할 수 있다. \nssmtp라는 패키지를 설치하고 설정을 해주면 큰 어려움 없이 쉘 명령으로 메일을 전송할 수 있다.\n\nssmtp의 가장 큰 단점이라면 첨부 파일을 보낼 수 없다는 것이다. \n만약 첨부파일 전송이 필요하다면 다른 종류의 메일 송신 프로그램을 사용하시기를 바란다.\n\nssmtp 사용 방법\n\nssmtp로 메일을 송신하기 위해서는 아래와 같이 3단계가 필요하다.\n\n\n ssmtp 패키지를 설치해야 한다.\n ssmtp 환경 설정이 필요하다.\n 형식에 맞는 메일 내용을 작성한 후에 ssmtp를 실행하면 된다.\n\n\nssmtp 패키지가 설치되어 있는지 확인하는 방법\n\nssmtp 패키지를 설치하는 방법을 설명하기에 앞서, \nssmtp 패키지가 설치되어 있는지부터 먼저 확인해보겠다. \n쉘에서 아래 명령을 실행하고 그 결과를 확인해보자.\n\n$ ssmtp --version\n\n\n만약 ssmtp가 설치되어 있다면 아래와 같은 결과가 나온다.\n\nssmtp: No recipients supplied - mail will not be sent\n\n\n만약 아래와 같은 결과가 나오면 ssmtp가 설치되어 있지 않으므로 설치해야 한다.\n\n명령어 'ssmtp' 을(를) 찾을 수 없습니다. 그러나 다음을 통해 설치할 수 있습니다:\nsudo apt install ssmtp\n\n\n친절하게도 ssmtp를 사용하기 위해서는 설치해야하는 패키지까지 알려준다.\n\nssmtp 패키지 설치 방법\n\nssmtp 패키지 설치하는 방법은 아주 간단하다. \n키를 추가하거나 소스 리스트를 추가해줄 필요도 없다. \n그저 쉘에서 아래 명령만 수행해주면 된다.\n\n$ sudo apt-get install ssmtp\n\n\nssmtp 환경 설정 방법 (gmail 기준)\n\n그렇다면 지금부터는 gmail 기준으로 ssmtp 환경 설정하는 방법에 대해서 설명하겠다. \n결론부터 이야기하자면 아래와 같이 설정하면 된다.\n\n$ sudo vi /etc/ssmtp/ssmtp.conf\n\n\n선호하는 편집기로 /etc/ssmtp/ssmtp.conf 설정 파일을 편집한다.\n\n아래와 같이 설정한다.\n\nroot=yourmail@gmail.com\nmailhub=smtp.gmail.com:587\nFromLineOverride=YES\nUseSTARTTLS=YES\nUseTSL=YES\nAuthUser=yourmail\nAuthPass=app password (16자리 문자)\n\n\n여기에서 주의할 것이 있다. \nAuthPass에 비밀번호를 입력하면 될 것 같지만, 실제로는 토큰을 입력해야 한다. \n앱 비밀번호를 입력해야 하는데, 이것은 계정 비밀 번호와는 다르다.\n\n관련 내용은 아래 사이트에 접속하면 앱 비밀번호 설정 방법에 대해서 확인할 수 있다.\n\ngmail 앱 비밀번호 로그인\n\nssmtp로 간단하게 메일을 전송하는 방법\n\n선호하는 편집기를 통해서 보낼 메일의 내용을 입력하면 된다. \nssmtp로 메일을 보내기 위해서는 정해진 포맷의 헤더를 포함해야 한다.\n\n\nTo: boyinblue@hanmail.net\nFrom: boyinblue: boyinblue@naver.com\nMIME-Version: 1.0\nContent-Type: text/html; charset=utf-8\nSubject: This is a test mail\nThis is a test message.\n\n\n위와 같이 메일을 작성했다면 아래와 같이 명령어 한 줄로 메일을 전송할 수 있다.\n\ncat email.txt | ssmtp -v -t\n\n\n\n[<-] 220 smtp.gmail.com ESMTP **************************** - gsmtp\n[->] EHLO parksejin-desktop\n[<-] 250 SMTPUTF8\n[->] STARTTLS\n[<-] 220 2.0.0 Ready to start TLS\n[->] EHLO parksejin-desktop\n[<-] 250 SMTPUTF8\n[->] AUTH LOGIN\n[<-] 334 ******\n[->] ******\n[<-] 334 ******\n[<-] 235 2.7.0 Accepted\n[->] MAIL FROM:<boyinblue: esregnet0409@gmail.com>\n[<-] 250 2.1.0 OK ******* - gsmtp\n[->] RCPT TO:<boyinblue@hanmail.net>\n[<-] 250 2.1.5 OK ******** - gsmtp\n[->] DATA\n[<-] 354 Go ahead *********** - gsmtp\n[->] Received: by parksejin-desktop (sSMTP sendmail emulation); Fri, 18 Mar 2022 11:13:52 +0900\n[->] Date: Fri, 18 Mar 2022 11:13:52 +0900\n[->] To: boyinblue@hanmail.net\n[->] From: boyinblue: esregnet0409@gmail.com\n[->] MIME-Version: 1.0\n[->] Content-Type: text/html; charset=utf-8\n[->] Subject: This is a test mail\n[->] This is a test message.\n[->] \n[->] .\n[<-] 250 2.0.0 OK ******* - gsmtp\n[->] QUIT\n[<-] 221 2.0.0 closing connection ***** - gsmtp\n\n\n“ssmtp: Cannot open mail:25” 에러 발생시\n\n만약 ssmtp: Cannot open mail:25라는 에러가 발생한다면, \nSMTP 서버 설정이 올바르지 않을 가능성이 있다. \n/etc/ssmtp/ssmtp.conf 파일을 열어서 mailhub 설정이 올바른지 확인해본다.\n\n$ sudo vi /etc/ssmtp/ssmtp.conf\n\n\n/etc/ssmtp/ssmtp.conf 파일의 퍼미션은 0640이다. \n따라서 편집을 위해서는 root 권한이 필요하다. \n혹시라도 mailhub=mail 로 되어 있으면 mailhub에 SMTP 서버 주소를 기입한다.\n\nmailhub=mail 부분을 mailhub=smtp.gmail.com로 변경해준다.\n\n필자의 경우는 gmail을 예로 입력했지만, 그 외의 다른 SMTP 주소를 사용하면 된다.\n\n/etc/ssmtp/ssmtp.conf 파일을 편집하려고 하였으나 내용이 비어있을 경우\n\n만약 vi /etc/ssmtp/ssmtp.conf 명령으로 파일 편집을 시도했는데, \n파일 내용이 완전히 비어있다면 퍼미션 문제이다.\n\n$ sudo ls -all /etc/ssmtp/ssmtp.conf\n\n\n sudo ls -all /etc/ssmtp/ssmtp.conf 명령으로 해당 파일의 퍼미션을 삺펴보면 0640으로 되어 있는 것을 알 수 있다.\n\n-rw-r----- 1 root mail 598 3월 17 16:43 /etc/ssmtp/ssmtp.conf\n\n\n즉, root만이 해당 파일을 편집할 수 있고, 읽기 권한은 mail 그룹만 가능하다. \n이 때는 sudo 명령을 통해서 root 권한으로 편집을 시도하면 된다.\n\n sudo vi /etc/ssmtp/ssmtp.conf 와 같이 sudo 명령으로 파일 편집기를 열었는지 다시 확인해보자.\n\n“Must issue a STARTTLS command first” 에러 발생시\n\n위와 같은 에러가 발생한다면 ssmtp.conf 파일을 열어서 UseSTARTTLS=YES와 같이 UseSTARTTLS 설정을 해주면 된다.\n\nroot=esregnet0409@gmail.com\nhostname=esregenet0409@gmail.com\nFromLineOverride=YES\n\n\n“ssmtp: Authorization failed (535 5.7.8)” 에러가 발생할 경우\n\n아래와 같이 Authorization failed 에러가 발생했다면 앱 비밀번호가 올바르지 않다는 것이다. \n앞서 언급했듯이 AuthPass는 비밀번호가 아니라 앱 비밀번호이다.\n\nssmtp: Authorization failed (535 5.7.8 https://support.google.com/mail/?p=BadCredentials j11-20020a63230b000000b00372a08b584asm6297113pgj.47 - gsmtp)\n\n\n이 때는 앱 비밀번호를 발급받아서 AuthPass에 넣어주면 된다. \n앱 비밀번호는 16자리짜리 문자열이다.\n\n“도메인을 찾지 못하여 메일 전송이 안 되는 경우”\n\n다음과 같은 DNS 오류가 발생한다면 hostname을 체크해보는게 좋다.\n\n주소를 찾을 수 없음\n\n도메인을 찾지 못하여 abc@abc.com 주소로 메일을 전송하지 못했습니다. \n오타나 불필요한 공백이 있는지 확인한 후 다시 시도하세요. \n\n응답은 다음과 같습니다. \n\nDNS Error: DNS type 'mx' lookup of 'hostname' responded with code NXDOMAIN Domain name not found\n\n\n이 때는 ssmtp.conf 설정 파일의 hostname을 체크해보시기 바란다. \n필자의 경우는 gmail 계정으로 ssmtp를 설정했고, \nhostname을 gmail의 smtp 서버 주소로 변경했더니 깔끔하게 문제가 해결되었다.\n\n기존에 잘못 입력된 hostname\n\nhostname=desktop\n\n\n아래와 같이 hostname에 이메일의 smtp 주소를 입력해주면 된다.\n\nhostname=smtp.gmail.com:587\n\n\ngmail 서비스에서 전송할 수 있는 할당량을 초과할 경우\n\n아래와 같은 메시지가 발생하면서 메일이 전송되지 않는다면 \n메일을 전송할 수 있는 할당량을 초과한 것이다.\n\nssmtp: 550 5.4.5 Daily user sending quota exceeded. - gsmtp\n\n\ngmail에서는 메일을 전송할 수 있는 할당량이 있다. \nGmail for Developers 문서\n\n해당 문제는 일정 시간이 지나면 자동적으로 해결된다. \n참고로 특정 날짜 1일간에 보낼 수 있는 메일 개수가 제한된 것이 아니고, \nAverage Moving 방식으로 쿼터제를 시행한다. \n혹시나 이런 문제가 자주 발생한다면 반복적으로 메일 발송을 과도하게 요청하고 있는것은 아닌지 체크하는게 좋다.\n\ndead.letter라는 파일이 생성되어서 파일 크기가 점점 커짐\n\n메일이 제대로 전송되지 못했을 경우 \ndead.letter 파일에 전송되지 못한 메일 데이터가 계속 쌓이게 된다. \n메일 발송이 정말 중요해서 꼭 전달될 필요가 없다면 그냥 삭제하기를 권한다.\n\ndead.letter 파일 정체\n\n결론\n\n이것으로 Ubuntu Linux에서 ssmtp 프로그램을 이용해서 메일을 전송하는 방법에 대한 설명을 모두 마친다.\n"]
Title : 자바스크립트에서 2차원 배열 선언 및 사용 방법
URL : /007_javascript/001.html
Description : 자바 스크립트에서 2차원 배열의 선언을 지원하지는 않지만, 약간의 트릭을 이용하여 2차원 배열을 선언할 수 있는 방법을 설명합니다.
Content : 2차원 배열의 선언

자바스크립트에서 2차원 배열의 선언은 다른 언어들과는 조금 다릅니다.
자바스크립트는 2차원 배열은 1차원 배열을 생성한 이후에 그 안에 다시 1차원 배열을 동적으로 할당하는 방식으로 생성할 수 있습니다.
다소 번거롭다고 생각될 수 있겠습니다 단점이 될 수도 있고, 장점이 될 수도 있습니다.

C에서의 2차원 배열 선언 및 사용 예시

우선 C언어에서의 2차원 배열 선언 및 사용에 대해서 잠깐 살펴볼께요.
C언어를 예시로 제시한 이유는 C언어에서의 2차원 배열 및 그 이상의 다차원 배열의 선언 및 사용이 아주 간단하면서도 직관적이기 때문입니다.

int arr[10][5];

arr[0][0] = 10;

printf("%d", arr[0][0]);


C언어에서는 위와 같이 손쉽게 2차원 배열을 선언하고, 값을 할당하고, 저장된 값을 읽어올 수 있습니다.
하지만 배열의 크기를 미리 선언해야하기 때문에 프로그램이 동작 중에 배열의 크기를 늘이거나 줄이기는 어렵습니다.
또한 행별로 다른 컬럼 수를 가지도록 하는 것도 불가능한 단점이 있습니다.

자바스크립트에서 2차원 배열을 생성하는 가장 간단한 방법

그럼 이번에는 자바스크립트에서 2차원 배열 선언은 어떻게 할 수 있을까요?
아쉽게도 자바스크립트에서는 C처럼 직관적이고 간단하게 2차원 배열을 생성할 수는 없습니다.
그렇지만 방법이 아예 없는 것은 아닙니다.
1차원 배열을 선언한 이후에 그 안에 다시 1차원 배열을 선언하면 됩니다.

var arr = new Array(10);
for( var i = 0 ; i < 10 ; i++ )
{
arr[i] = new Array(5);
}


자바스크립트에서는 위와 같이 2차원 배열을 선언할 수 있고,
C언어에서의 2차원 배열 선언보다는 조금 더 번거롭다는 것을 알 수 있습니다.

자바스크립트에서 2차원 배열을 생성하는 좀 더 좋은 방법

위의 스크립트를 조금 수정하면 rows 변수와 cols 변수를 이용해서 생성하는 것도 가능합니다.
거의 모든 프로그래밍 언어에서 값을 하드코딩해서 쓰는 방법은 좋은 방법이 아닙니다.
아래와 같이 행수(rows)와 열수(cols)를 변수로 선언해서 쓰는게 좋습니다.
왜냐하면, 이후에 행렬의 크기가 변경되었을 때 rows 값과 cols 값만 수정하면 되기 때문입니다.

var rows = 10;
var cols = 5;

var arr = new Array(rows);

for( var i = 0 ; i < rows ; rows++ )
{
arr[i] = new Array(cols);
}


자바스크립트에서 2차원 배열을 생성하는 가장 좋은 방법

만약 스크립트 안에서 여러개의 2차원 배열을 생성해야 한다면,
2차원 배열을 생성하는 부분을 함수화할 수 있습니다.

function create2DArray(rows, cols)
{
var arr = new Array(rows);
for (var i = 0; i < rows; i++) {
arr[i] = new Array(cols);
}
return arr;
}

var arr1 = create2DArray(10, 5);
var arr2 = create2DArray(3, 7);


2차원 배열을 생성하고 싶을 때마다 저 함수를 호출하면 간단하게 생성할 수 있습니다.

2차원 배열에 값을 저장하는 방법

그러면 위에서 생성한 2차원 배열에 값을 할당하는 방식은 어떻게 될까요?
사용 방법은 다행히 C언어와 유사합니다.
우선 값을 저장하는 방법입니다.

for (var i = 0; i < rows; i++)
{
for (var j = 0 ; j < cols ; j++)
{
arr[i][j] = i*10 + j;
}
}


위와 같은 방법으로 2차원 배열에 값을 저장할 수 있습니다.

2차원 배열에 저장된 값을 사용하는 방법

저장된 값을 사용하는 방법 역시도 아주 간단합니다.

document.write("[2][2]에 저장된 값 : ");
document.write(arr[2][2]);


2차원 배열에 저장된 값을 덤프(dump)하는 방법

혹은 for 문으로 배열을 순회하면서 2차원 배열 전체의 내용을 덤프(dump)하는 방법도 있습니다.

for (var i = 0; i < rows; i++)
{
for (var j = 0 ; j < cols ; j++)
{
document.write(arr[i][j]);
document.write(" ");
}
document.write("\n");
}


본 페이지에서 사용한 예시 전체

본 페이지에서 사용한 예시 전체를 하나의 스크립트로 보여드리겠습니다.

function create2DArray(rows, cols)
{
var arr = new Array(rows);
for (var i = 0; i < rows; i++) {
arr[i] = new Array(cols);
}
return arr;
}

var rows = 10;
var cols = 5;
var arr = create2DArray(rows, cols);

for (var i = 0; i < rows; i++)
{
for (var j = 0 ; j < cols ; j++)
{
arr[i][j] = i*10 + j;
}
}

for (var i = 0; i < rows; i++)
{
for (var j = 0 ; j < cols ; j++)
{
document.write(arr[i][j]);
document.write(" ");
}
document.write("<br>");
}


위의 스크립트를 수행하면 아래 화면과 같이 2차원 배열의 내용이 모두 출력됩니다.


["2차원 배열의 선언\n\n자바스크립트에서 2차원 배열의 선언은 다른 언어들과는 조금 다릅니다. \n자바스크립트는 2차원 배열은 1차원 배열을 생성한 이후에 그 안에 다시 1차원 배열을 동적으로 할당하는 방식으로 생성할 수 있습니다. \n다소 번거롭다고 생각될 수 있겠습니다 단점이 될 수도 있고, 장점이 될 수도 있습니다.\n\nC에서의 2차원 배열 선언 및 사용 예시\n\n우선 C언어에서의 2차원 배열 선언 및 사용에 대해서 잠깐 살펴볼께요. \nC언어를 예시로 제시한 이유는 C언어에서의 2차원 배열 및 그 이상의 다차원 배열의 선언 및 사용이 아주 간단하면서도 직관적이기 때문입니다.\n\nint arr[10][5];\n\narr[0][0] = 10;\n\nprintf(\"%d\", arr[0][0]);\n\n\nC언어에서는 위와 같이 손쉽게 2차원 배열을 선언하고, 값을 할당하고, 저장된 값을 읽어올 수 있습니다. \n하지만 배열의 크기를 미리 선언해야하기 때문에 프로그램이 동작 중에 배열의 크기를 늘이거나 줄이기는 어렵습니다. \n또한 행별로 다른 컬럼 수를 가지도록 하는 것도 불가능한 단점이 있습니다.\n\n자바스크립트에서 2차원 배열을 생성하는 가장 간단한 방법\n\n그럼 이번에는 자바스크립트에서 2차원 배열 선언은 어떻게 할 수 있을까요? \n아쉽게도 자바스크립트에서는 C처럼 직관적이고 간단하게 2차원 배열을 생성할 수는 없습니다. \n그렇지만 방법이 아예 없는 것은 아닙니다. \n1차원 배열을 선언한 이후에 그 안에 다시 1차원 배열을 선언하면 됩니다.\n\nvar arr = new Array(10);\nfor( var i = 0 ; i < 10 ; i++ )\n{\n arr[i] = new Array(5);\n}\n\n\n자바스크립트에서는 위와 같이 2차원 배열을 선언할 수 있고, \nC언어에서의 2차원 배열 선언보다는 조금 더 번거롭다는 것을 알 수 있습니다.\n\n자바스크립트에서 2차원 배열을 생성하는 좀 더 좋은 방법\n\n위의 스크립트를 조금 수정하면 rows 변수와 cols 변수를 이용해서 생성하는 것도 가능합니다. \n거의 모든 프로그래밍 언어에서 값을 하드코딩해서 쓰는 방법은 좋은 방법이 아닙니다. \n아래와 같이 행수(rows)와 열수(cols)를 변수로 선언해서 쓰는게 좋습니다. \n왜냐하면, 이후에 행렬의 크기가 변경되었을 때 rows 값과 cols 값만 수정하면 되기 때문입니다.\n\nvar rows = 10;\nvar cols = 5;\n\nvar arr = new Array(rows);\n\nfor( var i = 0 ; i < rows ; rows++ )\n{\n arr[i] = new Array(cols);\n}\n\n\n자바스크립트에서 2차원 배열을 생성하는 가장 좋은 방법\n\n만약 스크립트 안에서 여러개의 2차원 배열을 생성해야 한다면, \n2차원 배열을 생성하는 부분을 함수화할 수 있습니다.\n\nfunction create2DArray(rows, cols)\n{\n var arr = new Array(rows);\n for (var i = 0; i < rows; i++) {\n arr[i] = new Array(cols);\n }\n return arr;\n}\n\nvar arr1 = create2DArray(10, 5);\nvar arr2 = create2DArray(3, 7);\n\n\n2차원 배열을 생성하고 싶을 때마다 저 함수를 호출하면 간단하게 생성할 수 있습니다.\n\n2차원 배열에 값을 저장하는 방법\n\n그러면 위에서 생성한 2차원 배열에 값을 할당하는 방식은 어떻게 될까요? \n사용 방법은 다행히 C언어와 유사합니다. \n우선 값을 저장하는 방법입니다.\n\nfor (var i = 0; i < rows; i++)\n{\n for (var j = 0 ; j < cols ; j++)\n {\n arr[i][j] = i*10 + j;\n }\n}\n\n\n위와 같은 방법으로 2차원 배열에 값을 저장할 수 있습니다.\n\n2차원 배열에 저장된 값을 사용하는 방법\n\n저장된 값을 사용하는 방법 역시도 아주 간단합니다.\n\ndocument.write(\"[2][2]에 저장된 값 : \");\ndocument.write(arr[2][2]);\n\n\n2차원 배열에 저장된 값을 덤프(dump)하는 방법\n\n혹은 for 문으로 배열을 순회하면서 2차원 배열 전체의 내용을 덤프(dump)하는 방법도 있습니다.\n\nfor (var i = 0; i < rows; i++)\n{\n for (var j = 0 ; j < cols ; j++)\n {\n document.write(arr[i][j]);\n document.write(\" \");\n }\n document.write(\"", "\");\n}\n\n\n본 페이지에서 사용한 예시 전체\n\n본 페이지에서 사용한 예시 전체를 하나의 스크립트로 보여드리겠습니다.\n\nfunction create2DArray(rows, cols)\n{\n var arr = new Array(rows);\n for (var i = 0; i < rows; i++) {\n arr[i] = new Array(cols);\n }\n return arr;\n}\n\nvar rows = 10;\nvar cols = 5;\nvar arr = create2DArray(rows, cols);\n\nfor (var i = 0; i < rows; i++)\n{\n for (var j = 0 ; j < cols ; j++)\n {\n arr[i][j] = i*10 + j;\n }\n}\n\nfor (var i = 0; i < rows; i++)\n{\n for (var j = 0 ; j < cols ; j++)\n {\n document.write(arr[i][j]);\n document.write(\" \");\n }\n document.write(\"<br>\");\n}\n\n\n위의 스크립트를 수행하면 아래 화면과 같이 2차원 배열의 내용이 모두 출력됩니다.\n\n\n"]
Title : GitHub Pages 사이트맵을 자동으로 생성해주는 bash 스크립트
URL : /002_github_blog/007.html
Description : 사이트맵을 자동으로 생성하는 bash 스크립트 예제를 제공합니다.
Content : 최근 GitHub Pages를 접하게 되면서 신선한 충격을 받았습니다.
기존의 네이버 블로그와 티스토리를 운영하면서 느꼈던 제약에서 벗어나
좀 더 자유롭게 블로그를 운영할 수 있어서 참 만족스럽습니다.

반면, 검색 엔진에 노출시키려면 사이트맵, RSS, robots.txt 등의 파일을 직접 생성해야 되는 점은 다소 불편합니다.
네이버 블로그나 티스토리 블로그에서는 글을 발행하면 자동으로 사이트맵에도 추가되고 금새 검색 엔진에 반영이 됩니다.
GitHub Pages는 페이지를 업로드한 이후에 별도로 사이트맵 파일을 편집해줘야하는 번거로움이 있습니다.

본 페이지에서는 bash 스크립트를 이용해서 xml 형식의 사이트맵 파일을 생성하는 방법에 대해서 설명드리겠습니다.
훈련시에 땀 한 방울이 전시에 피 한 방울을 대체한다고 하지요?
잘 작성한 스크립트 하나는 열일을 합니다.

아쉽게도 GitHub Pages에서는 PHP와 같이 Sever-side에서 동작하는 스크립트는 사용할 수 없습니다.
대신 GitHub Pages에 글을 업로드한 이후에 자동 생성 스크립트를 수동으로 한 번 수행하거나,
24시간 동작하는 리눅스 PC가 있다면 crontab을 걸어두는 것도 괜찮은 방법이라고 생각됩니다.

사이트맵이란?

사이트맵이라는 것은 검색 엔진이 해당 사이트의 페이지들을 크롤링할 때 사용하는 파일입니다.
해당 사이트에 있는 페이지 목록들을 검색 엔진의 로봇들이 수집해갈 수 있도록 돕는 파일입니다.
보통 xml 형식의 파일로 제공되지만 아주 간단한 텍스트 파일로도 작성할 수 있습니다.

본 페이지에서는 xml 형식의 사이트맵과 txt 형식의 사이트맵을 모두 생성하는 스크립트를 제공합니다.

자동으로 사이트맵을 생성해주는 bash 스크립트

성격이 급하신 분들을 위해서 스크립트부터 먼저 보여드리겠습니다.
최종 스크립트에서 다운로드 받으시면 됩니다.
최종 스크립트는 아래 본문의 스크립트와 다소 차이가 날 수 있습니다.
디렉토리 구조가 다를 수 있으므로 상황에 맞게 수정하셔서 사용하시면 되겠습니다.

#!/bin/bash

SITEMAP_XML_FILE="../sitemap.xml"
SITEMAP_XML_FILE_TMP="/tmp/sitemap.xml"

SITEMAP_TXT_FILE="../sitemap.txt"
SITEMAP_TXT_FILE_TMP="/tmp/sitemap.txt"

HOMEPAGE_URL="https://boyinblue.github.io"

rm -rf "$SITEMAP_XML_FILE_TMP"
rm -rf "$SITEMAP_TXT_FILE_TMP"

function print_header()
{
echo '<?xml version="1.0" encoding="UTF-8"?>'
echo '<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'
}

function print_tail()
{
echo '</urlset>'
}

function print_list_xml()
{
dirs=$(ls)
for dir in ${dirs[@]}
do
if [[ "${dir:0:3}" =~ ^[0-9]+$ ]]; then
files=$(ls ${dir}/*.md)
for file in ${files[@]}
do
lastmod=$(date +"%m-%d-%YT%H:%M:%S%:z" -r ${file})
echo "<url>"
echo "<loc>${HOMEPAGE_URL}/${file/.md/.html}</loc>"
echo "<lastmod>${lastmod}</lastmod>"
echo "<changefreq>weekly</changefreq>"
echo "</url>"
done
fi
done
}

function print_list_txt()
{
dirs=$(ls)
for dir in ${dirs[@]}
do
if [[ "${dir:0:3}" =~ ^[0-9]+$ ]]; then
files=$(ls ${dir}/*.md)
for file in ${files[@]}
do
echo "${HOMEPAGE_URL}/${file/.md/.html}"
done
fi
done
}

pushd ..
print_header >> ${SITEMAP_XML_FILE_TMP}
print_list_xml >> ${SITEMAP_XML_FILE_TMP}
print_tail >> ${SITEMAP_XML_FILE_TMP}

print_list_txt >> ${SITEMAP_TXT_FILE_TMP}
popd

diff=$(diff $SITEMAP_XML_FILE_TMP $SITEMAP_XML_FILE)
if [ "${diff}" != "" ]; then
cp ${SITEMAP_XML_FILE_TMP} ${SITEMAP_XML_FILE}
fi

diff=$(diff $SITEMAP_TXT_FILE_TMP $SITEMAP_TXT_FILE)
if [ "${diff}" != "" ]; then
cp ${SITEMAP_TXT_FILE_TMP} ${SITEMAP_TXT_FILE}
fi


스크립트 설명

우선 제 GitHub Pages의 페이지 구조는 아래와 같습니다.
숫자 3자리와 언더스코어로 시작되는 디렉토리 내부에는,
또 다시 숫자 3자리의 일련번호를 갖는 md 파일이 존재합니다.


/

001_GitHub_API

001.md
002.md


002_GitHub_Pages

001.md
002.md


003_Jenkins

001.md
002.md






예를 들면 /001_GitHub_API/001.md 파일은 /001_GitHub_API/001.html 경로로 사이트맵에 추가되면 됩니다.
bash 문법에 익숙하신 분들은 위의 스크립트를 간단하게 이해하실 수 있을 것입니다.
수행 절차를 간략하게 설명드리면 아래와 같습니다.


001_*형식의 이름을 가진 1차 디렉토리 목록을 가져와서 2번 과정을 수행합니다.
`001’ 형식의 이름을 가진 md 파일을 가져와서 3번 과정을 수행합니다.
.md 확장자를 html로 추가하여 xml 형식으로 /tmp/sitemap.xml 파일을 생성합니다.
위의 3번 과정을 txt 형식으로 /tmp/sitemap.txt 파일을 생성합니다.
/tmp/sitemap.xml 파일과 sitemap.xml 파일을 비교하여 변경점이 있으면 sitemap.xml 파일에 덮어씁니다.
/tmp/sitemap.txt 파일과 sitemap.txt 파일을 비교하여 변경점이 있으면 sitemap.txt 파일에 덮어씁니다.


다소 길어보이지만 찬찬히 살펴보시면 큰 어려움 없이 스크립트를 이해하실 수 있을 것입니다.

이상으로 bash 스크립트를 이용해서 사이트맵 파일을 자동으로 생성하는 방법에 대해서 설명드렸습니다.
["최근 GitHub Pages를 접하게 되면서 신선한 충격을 받았습니다. \n기존의 네이버 블로그와 티스토리를 운영하면서 느꼈던 제약에서 벗어나 \n좀 더 자유롭게 블로그를 운영할 수 있어서 참 만족스럽습니다.\n\n반면, 검색 엔진에 노출시키려면 사이트맵, RSS, robots.txt 등의 파일을 직접 생성해야 되는 점은 다소 불편합니다. \n네이버 블로그나 티스토리 블로그에서는 글을 발행하면 자동으로 사이트맵에도 추가되고 금새 검색 엔진에 반영이 됩니다. \nGitHub Pages는 페이지를 업로드한 이후에 별도로 사이트맵 파일을 편집해줘야하는 번거로움이 있습니다.\n\n본 페이지에서는 bash 스크립트를 이용해서 xml 형식의 사이트맵 파일을 생성하는 방법에 대해서 설명드리겠습니다. \n훈련시에 땀 한 방울이 전시에 피 한 방울을 대체한다고 하지요? \n잘 작성한 스크립트 하나는 열일을 합니다.\n\n아쉽게도 GitHub Pages에서는 PHP와 같이 Sever-side에서 동작하는 스크립트는 사용할 수 없습니다. \n대신 GitHub Pages에 글을 업로드한 이후에 자동 생성 스크립트를 수동으로 한 번 수행하거나, \n24시간 동작하는 리눅스 PC가 있다면 crontab을 걸어두는 것도 괜찮은 방법이라고 생각됩니다.\n\n사이트맵이란?\n\n사이트맵이라는 것은 검색 엔진이 해당 사이트의 페이지들을 크롤링할 때 사용하는 파일입니다. \n해당 사이트에 있는 페이지 목록들을 검색 엔진의 로봇들이 수집해갈 수 있도록 돕는 파일입니다. \n보통 xml 형식의 파일로 제공되지만 아주 간단한 텍스트 파일로도 작성할 수 있습니다.\n\n본 페이지에서는 xml 형식의 사이트맵과 txt 형식의 사이트맵을 모두 생성하는 스크립트를 제공합니다.\n\n자동으로 사이트맵을 생성해주는 bash 스크립트\n\n성격이 급하신 분들을 위해서 스크립트부터 먼저 보여드리겠습니다. \n최종 스크립트에서 다운로드 받으시면 됩니다. \n최종 스크립트는 아래 본문의 스크립트와 다소 차이가 날 수 있습니다. \n디렉토리 구조가 다를 수 있으므로 상황에 맞게 수정하셔서 사용하시면 되겠습니다.\n\n#!/bin/bash\n\nSITEMAP_XML_FILE=\"../sitemap.xml\"\nSITEMAP_XML_FILE_TMP=\"/tmp/sitemap.xml\"\n\nSITEMAP_TXT_FILE=\"../sitemap.txt\"\nSITEMAP_TXT_FILE_TMP=\"/tmp/sitemap.txt\"\n\nHOMEPAGE_URL=\"https://boyinblue.github.io\"\n\nrm -rf \"$SITEMAP_XML_FILE_TMP\"\nrm -rf \"$SITEMAP_TXT_FILE_TMP\"\n\nfunction print_header()\n{\n echo '<?xml version=\"1.0\" encoding=\"UTF-8\"?>'\n echo '<urlset xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd\" xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">' \n}\n\nfunction print_tail()\n{\n echo '</urlset>'\n}\n\nfunction print_list_xml()\n{\n dirs=$(ls)\n for dir in ${dirs[@]}\n do\n if [[ \"${dir:0:3}\" =~ ^[0-9]+$ ]]; then\n files=$(ls ${dir}/*.md)\n for file in ${files[@]}\n do\n lastmod=$(date +\"%m-%d-%YT%H:%M:%S%:z\" -r ${file})\n\techo \"<url>\"\n echo \"<loc>${HOMEPAGE_URL}/${file/.md/.html}</loc>\"\n\techo \"<lastmod>${lastmod}</lastmod>\"\n\techo \"<changefreq>weekly</changefreq>\"\n\techo \"</url>\"\n done\n fi\n done\n}\n\nfunction print_list_txt()\n{\n dirs=$(ls)\n for dir in ${dirs[@]}\n do\n if [[ \"${dir:0:3}\" =~ ^[0-9]+$ ]]; then\n files=$(ls ${dir}/*.md)\n for file in ${files[@]}\n do\n echo \"${HOMEPAGE_URL}/${file/.md/.html}\"\n done\n fi\n done\n}\n\npushd ..\nprint_header >> ${SITEMAP_XML_FILE_TMP}\nprint_list_xml >> ${SITEMAP_XML_FILE_TMP}\nprint_tail >> ${SITEMAP_XML_FILE_TMP}\n\nprint_list_txt >> ${SITEMAP_TXT_FILE_TMP}\npopd\n\ndiff=$(diff $SITEMAP_XML_FILE_TMP $SITEMAP_XML_FILE)\nif [ \"${diff}\" != \"\" ]; then\n cp ${SITEMAP_XML_FILE_TMP} ${SITEMAP_XML_FILE}\nfi\n\ndiff=$(diff $SITEMAP_TXT_FILE_TMP $SITEMAP_TXT_FILE)\nif [ \"${diff}\" != \"\" ]; then\n cp ${SITEMAP_TXT_FILE_TMP} ${SITEMAP_TXT_FILE}\nfi\n\n\n스크립트 설명\n\n우선 제 GitHub Pages의 페이지 구조는 아래와 같습니다. \n숫자 3자리와 언더스코어로 시작되는 디렉토리 내부에는, \n또 다시 숫자 3자리의 일련번호를 갖는 md 파일이 존재합니다.\n\n\n /\n \n 001_GitHub_API\n \n 001.md\n 002.md\n \n \n 002_GitHub_Pages\n \n 001.md\n 002.md\n \n \n 003_Jenkins\n \n 001.md\n 002.md\n \n \n \n \n\n\n예를 들면 /001_GitHub_API/001.md 파일은 /001_GitHub_API/001.html 경로로 사이트맵에 추가되면 됩니다. \nbash 문법에 익숙하신 분들은 위의 스크립트를 간단하게 이해하실 수 있을 것입니다. \n수행 절차를 간략하게 설명드리면 아래와 같습니다.\n\n\n 001_*형식의 이름을 가진 1차 디렉토리 목록을 가져와서 2번 과정을 수행합니다.\n `001’ 형식의 이름을 가진 md 파일을 가져와서 3번 과정을 수행합니다.\n .md 확장자를 html로 추가하여 xml 형식으로 /tmp/sitemap.xml 파일을 생성합니다.\n 위의 3번 과정을 txt 형식으로 /tmp/sitemap.txt 파일을 생성합니다.\n /tmp/sitemap.xml 파일과 sitemap.xml 파일을 비교하여 변경점이 있으면 sitemap.xml 파일에 덮어씁니다.\n /tmp/sitemap.txt 파일과 sitemap.txt 파일을 비교하여 변경점이 있으면 sitemap.txt 파일에 덮어씁니다.\n\n\n다소 길어보이지만 찬찬히 살펴보시면 큰 어려움 없이 스크립트를 이해하실 수 있을 것입니다.\n\n이상으로 bash 스크립트를 이용해서 사이트맵 파일을 자동으로 생성하는 방법에 대해서 설명드렸습니다.\n"]
Title : Jenkins Hook이 제대로 전달되지 못하는 경우 해결 방법 (GitHub Pull Request Builder 오류 및 역방향 프록시 설정 오류)
URL : /003_jenkins/001.html
Description : Jenkins에서 GitHub Pull Request Builder가 역방향 프록시 설정 오류 메시지가 발생하면서 빌드되지 않는 오류를 해결하는 방법에 대해서 설명합니다.
Content : GitHub와 Jenkins를 연동해두면, GitHub에 Pull Request가 등록되면 자동으로 Jenkins쪽에 Hook이 전달됩니다.
GitHub Pull Request Builder가 제대로 트리거되지 못하는 문제가 발생했습니다.
Jenkins의 GitHub Pull Request Builder가 제대로 시작되지 못하는 원인은 여러가지가 있겠습니다만,
그 중에서도 특별히 Jenkins 서버의 주소 설정이 올바르지 않아서 “역방향 프록시 설정 오류” 에러가 뜨는 상태의 문제에 대해서 기술하고자 합니다.

Jenkins의 GitHub Pull Request Builder란?

어쩌면 TMI일 수도 있겠지만, Jenkins에서는 GitHub에서 전달되는 훅(Hook)을 통해서 Pull Request 이벤트가 발생되었을 때 해당 Pull Request를 감지하여 자동 빌드 및 테스트 자동화 시스템을 구성할 수 있기 지원하고 있습니다.
즉, GitHub에 Pull Request가 생성되면 그 이벤트를 Jenkins에 전달하고,
Jenkins에서는 해당 payload를 분석하여 해당 PR(Pull Request)에 대한 일련의 과정을 처리하고 그 결과를 다시 GitHub쪽에 전달하는 방식입니다.

이 자동화 시스템의 장점이라고 한다면, 컴파일 에러 또는 링크 에러를 유발하는 Pull Request가 target branch(대상 브렌치)에 머지되는 것을 막을 수 있는 장점이 있습니다.
또한 빌드 테스트 외에도 테스트 자동화 시스템을 구축해두면, TC(테스트 케이스)에 따라서 일련의 테스트 과정을 거친 후에 그 결과를 GitHub에 자동으로 리포팅하므로 어느정도 동작성이 검증된 소스 코드가 target branch에 머지되는 :

문제의 상황 기술

회사에서 GitHub와 Jenkins와 SonarQube 시스템을 연동하여 빌드 및 테스트 자동화 환경을 구축해서 잘 운영하던 중이었습니다.
최근에 서버를 옮기면서 기존에 잘 되던 GitHub Pull Request Builder 기능이 제대로 동작하지 않는 문제가 발생하였습니다.
GitHub에서는 Hook이 정상적으로 전송이 되고 Jenkins 서버로부터 정상적으로 응답을 받은 것으로 표시되고 있어서 문제의 원인이 Jenkins-side에 있다고 생각을 했습니다.

결정적 단서 : 역방향 프록시 설정 오류

젠킨스 설정에 들어가서 설정이 올바른지 확인하는 도중에 “역방향 프록시 설정 오류”라는 메시지가 눈에 들어왔습니다.
이것이 GitHub Pull Request Builder가 제대로 동작하지 못하게 하는 원인이라는 의심이 강하게 들었습니다.

해결 방법 : Jenkins 설정에서 URL 설정

아래 메뉴로 들어가서 Jenkins URL 설정을 살펴봅니다.


Jenkins 관리

시스템 설정

Jenkins URL






제 경우는 위의 주소가 올바르지 않아서 발생하였습니다.
서버 이전하기 전의 IP를 삭제하고, 새로운 서버의 IP로 설정해줬더니
Pull Requester Build가 동작하지 않는 문제가 깔끔하게 해결되었습니다.

만약 URL 주소가 http://localhost:8080/으로 되어 있는 경우에도
역방향 프록시 오류를 유발할 수 있으므로
반드시 Jenkins 서버의 URL을 올바르게 입력해주시기 바랍니다.

["GitHub와 Jenkins를 연동해두면, GitHub에 Pull Request가 등록되면 자동으로 Jenkins쪽에 Hook이 전달됩니다. \nGitHub Pull Request Builder가 제대로 트리거되지 못하는 문제가 발생했습니다. \nJenkins의 GitHub Pull Request Builder가 제대로 시작되지 못하는 원인은 여러가지가 있겠습니다만, \n그 중에서도 특별히 Jenkins 서버의 주소 설정이 올바르지 않아서 “역방향 프록시 설정 오류” 에러가 뜨는 상태의 문제에 대해서 기술하고자 합니다.\n\nJenkins의 GitHub Pull Request Builder란?\n\n어쩌면 TMI일 수도 있겠지만, Jenkins에서는 GitHub에서 전달되는 훅(Hook)을 통해서 Pull Request 이벤트가 발생되었을 때 해당 Pull Request를 감지하여 자동 빌드 및 테스트 자동화 시스템을 구성할 수 있기 지원하고 있습니다. \n즉, GitHub에 Pull Request가 생성되면 그 이벤트를 Jenkins에 전달하고, \nJenkins에서는 해당 payload를 분석하여 해당 PR(Pull Request)에 대한 일련의 과정을 처리하고 그 결과를 다시 GitHub쪽에 전달하는 방식입니다.\n\n이 자동화 시스템의 장점이라고 한다면, 컴파일 에러 또는 링크 에러를 유발하는 Pull Request가 target branch(대상 브렌치)에 머지되는 것을 막을 수 있는 장점이 있습니다. \n또한 빌드 테스트 외에도 테스트 자동화 시스템을 구축해두면, TC(테스트 케이스)에 따라서 일련의 테스트 과정을 거친 후에 그 결과를 GitHub에 자동으로 리포팅하므로 어느정도 동작성이 검증된 소스 코드가 target branch에 머지되는 :\n\n문제의 상황 기술\n\n회사에서 GitHub와 Jenkins와 SonarQube 시스템을 연동하여 빌드 및 테스트 자동화 환경을 구축해서 잘 운영하던 중이었습니다. \n최근에 서버를 옮기면서 기존에 잘 되던 GitHub Pull Request Builder 기능이 제대로 동작하지 않는 문제가 발생하였습니다.\nGitHub에서는 Hook이 정상적으로 전송이 되고 Jenkins 서버로부터 정상적으로 응답을 받은 것으로 표시되고 있어서 문제의 원인이 Jenkins-side에 있다고 생각을 했습니다.\n\n결정적 단서 : 역방향 프록시 설정 오류\n\n젠킨스 설정에 들어가서 설정이 올바른지 확인하는 도중에 “역방향 프록시 설정 오류”라는 메시지가 눈에 들어왔습니다. \n이것이 GitHub Pull Request Builder가 제대로 동작하지 못하게 하는 원인이라는 의심이 강하게 들었습니다.\n\n해결 방법 : Jenkins 설정에서 URL 설정\n\n아래 메뉴로 들어가서 Jenkins URL 설정을 살펴봅니다.\n\n\n Jenkins 관리\n \n 시스템 설정\n \n Jenkins URL\n \n \n \n \n\n\n제 경우는 위의 주소가 올바르지 않아서 발생하였습니다. \n서버 이전하기 전의 IP를 삭제하고, 새로운 서버의 IP로 설정해줬더니 \nPull Requester Build가 동작하지 않는 문제가 깔끔하게 해결되었습니다.\n\n만약 URL 주소가 http://localhost:8080/으로 되어 있는 경우에도 \n역방향 프록시 오류를 유발할 수 있으므로 \n반드시 Jenkins 서버의 URL을 올바르게 입력해주시기 바랍니다.\n\n"]
Title : GitHub Pages에서 php 문법을 사용 가능할까?
URL : /002_github_blog/006.html
Description : GitHub Pages에서 php 문법 사용 가능 여부에 대해서 설명합니다.
Content : 최근에 GitHub Pages를 접하면서 깜짝 깜짝 놀라고 있습니다.
기존의 네이버 블로그와 티스토리 블로그와 같은 정형화된 블로그들의 한계를 맞보고,
새로운 웹서비스를 찾아보다가 GitHub Pages가 눈에 들어왔습니다.

Markdown 문법을 통해서 손쉽고도 시원시원하게 글을 작성할 수 있는데다가,
하루에 발행할 수 있는 글의 개수에 제한이 없다는건 엄청난 메리트입니다.
또한 구글 애드센스를 달 수 있기 때문에 수익형 블로그를 꿈꾸는 저에게 딱 맞는 웹서비스임에 틀림없다고 판단했습니다.

기존 블로그 서비스들은 robots.txt, RSS, 사이트 맵 등을 전혀 신경 쓸 필요가 없었습니다.
반면, GitHub Pages의 경우는 직접 robots.txt, sitemap.xml 파일 등을 생성해줘야 하기 때문에 이 부분이 다소 불편한 점이 있는 것 같습니다.

robots.txt 파일의 경우는 없어도 무방하고, 수동으로 작성해줘도 됩니다.
반면, 사이트 맵의 경우 하위 페이지가 생성될 때마다 갱신해줘야하므로 동적으로 자동 생성하지 않으면 여간 불편하게 아닐 수 없습니다.

sitemap.xml 파일을 동적으로 생성할 수 있는 방법들은 여러가지가 있습니다. xml 문법을 이용해도 되고, php, java, bash 등 자동으로 생성할 수 있는 방법들은 무궁무진합니다.

그리하여 GitHub Pages에서 php 문법을 사용 가능한지에 대해서 궁금증이 발동하기 시작했습니다. 과면 GitHub Pages에서 php 문법을 지원할까요?

GitHub Pages에서 php 문법이 동작하는지 확인해보자!

자, 그럼 지금부터 GitHub Pages에 php 문법이 동작하는지 확인해보겠습니다.
https://boyinblue.github.io의 root 디렉토리에 test.php 파일을 생성해서 < phpinfo()? ?>를 입력합니다.

만약 GitHub Pages에서 php를 지원한다면 https//boyinblue.github.io/test/test.php 경로로 접속했을 때 phpinfo()? 구문이 정상적으로 동작할 것입니다.

<?
phpinfo();
?>


위와 같이 작성을 완료하고 https://boyinblue.github.io/test/test.php 경로로 접속을 시도하면 그냥 test.php 파일이 다운로드됩니다.
아쉽게도, GitHub Pages는 PHP 문법을 지원하지 않는 것을 알 수 있습니다.

GitHub Pages Article 확인

실제로 php가 동작하지 않는 것을 확인했지만, 실제로 GitHub Pages Article 을 살펴보겠습니다.



위의 이미지는 GitHub Pages 문서에 명시된 부분을 캡쳐한 내용입니다.
“GitHub Pages does not support server-side languages such as PHP, Ruby, or Python.” 라는 문구가 보입니다. GitHub Pages는 PHP, Ruby, Python과 같은 서버에서 동작하는 언어들을 지원하지 않는다는 내용입니다.

PHP 대신 Jekyll 사용을 추천

아쉽게도 GitHub Pages에서 PHP와 같은 dynamic pages를 지원하지는 않지만
Jekyll을 통해서 정적 페이지를 생성하는 것을 지원을 하는 것을 알 수 있습니다.
실제로 GitHub Pages는 기본적으로 Jekyll을 제공하고 있습니다.
이 때문에 우리가 GitPages의 최상위 경로에 어떤 디자인을 정의하지 않더라도
어느정도 페이지의 디자인이 볼만하다는 장점이 있습니다.

Jekyll을 사용하고 싶지 않다면?

만약 Jekyll을 사용하고 싶지 않다면 취상위 디렉토리에 .nojekyll 이라는 빈 파일을 생성하면 됩니다.

결론

GitHub Pages에서 PHP와 같이 Server-side에서 동작하는 동적 페이지를 구현할 수는 없습니다. 대신 Jekyll을 이용해서 정적 페이지는 얼마든지 생성할 수 있습니다. 만약, Jekyll을 사용하고 싶지 않으면 최상위 디렉토리에 .nojekyll 이라는 빈 파일을 생성하면 되겠습니다.

이상입니다.
["최근에 GitHub Pages를 접하면서 깜짝 깜짝 놀라고 있습니다. \n기존의 네이버 블로그와 티스토리 블로그와 같은 정형화된 블로그들의 한계를 맞보고, \n새로운 웹서비스를 찾아보다가 GitHub Pages가 눈에 들어왔습니다.\n\nMarkdown 문법을 통해서 손쉽고도 시원시원하게 글을 작성할 수 있는데다가, \n하루에 발행할 수 있는 글의 개수에 제한이 없다는건 엄청난 메리트입니다. \n또한 구글 애드센스를 달 수 있기 때문에 수익형 블로그를 꿈꾸는 저에게 딱 맞는 웹서비스임에 틀림없다고 판단했습니다.\n\n기존 블로그 서비스들은 robots.txt, RSS, 사이트 맵 등을 전혀 신경 쓸 필요가 없었습니다. \n반면, GitHub Pages의 경우는 직접 robots.txt, sitemap.xml 파일 등을 생성해줘야 하기 때문에 이 부분이 다소 불편한 점이 있는 것 같습니다.\n\nrobots.txt 파일의 경우는 없어도 무방하고, 수동으로 작성해줘도 됩니다. \n반면, 사이트 맵의 경우 하위 페이지가 생성될 때마다 갱신해줘야하므로 동적으로 자동 생성하지 않으면 여간 불편하게 아닐 수 없습니다.\n\nsitemap.xml 파일을 동적으로 생성할 수 있는 방법들은 여러가지가 있습니다. xml 문법을 이용해도 되고, php, java, bash 등 자동으로 생성할 수 있는 방법들은 무궁무진합니다.\n\n그리하여 GitHub Pages에서 php 문법을 사용 가능한지에 대해서 궁금증이 발동하기 시작했습니다. 과면 GitHub Pages에서 php 문법을 지원할까요?\n\nGitHub Pages에서 php 문법이 동작하는지 확인해보자!\n\n자, 그럼 지금부터 GitHub Pages에 php 문법이 동작하는지 확인해보겠습니다. \nhttps://boyinblue.github.io의 root 디렉토리에 test.php 파일을 생성해서 < phpinfo()? ?>를 입력합니다.\n\n만약 GitHub Pages에서 php를 지원한다면 https//boyinblue.github.io/test/test.php 경로로 접속했을 때 phpinfo()? 구문이 정상적으로 동작할 것입니다.\n\n<?\n phpinfo();\n?>\n\n\n위와 같이 작성을 완료하고 https://boyinblue.github.io/test/test.php 경로로 접속을 시도하면 그냥 test.php 파일이 다운로드됩니다. \n아쉽게도, GitHub Pages는 PHP 문법을 지원하지 않는 것을 알 수 있습니다.\n\nGitHub Pages Article 확인\n\n실제로 php가 동작하지 않는 것을 확인했지만, 실제로 GitHub Pages Article 을 살펴보겠습니다.\n\n\n\n위의 이미지는 GitHub Pages 문서에 명시된 부분을 캡쳐한 내용입니다. \n“GitHub Pages does not support server-side languages such as PHP, Ruby, or Python.” 라는 문구가 보입니다. GitHub Pages는 PHP, Ruby, Python과 같은 서버에서 동작하는 언어들을 지원하지 않는다는 내용입니다.\n\nPHP 대신 Jekyll 사용을 추천\n\n아쉽게도 GitHub Pages에서 PHP와 같은 dynamic pages를 지원하지는 않지만 \nJekyll을 통해서 정적 페이지를 생성하는 것을 지원을 하는 것을 알 수 있습니다. \n실제로 GitHub Pages는 기본적으로 Jekyll을 제공하고 있습니다. \n이 때문에 우리가 GitPages의 최상위 경로에 어떤 디자인을 정의하지 않더라도 \n어느정도 페이지의 디자인이 볼만하다는 장점이 있습니다.\n\nJekyll을 사용하고 싶지 않다면?\n\n만약 Jekyll을 사용하고 싶지 않다면 취상위 디렉토리에 .nojekyll 이라는 빈 파일을 생성하면 됩니다.\n\n결론\n\nGitHub Pages에서 PHP와 같이 Server-side에서 동작하는 동적 페이지를 구현할 수는 없습니다. 대신 Jekyll을 이용해서 정적 페이지는 얼마든지 생성할 수 있습니다. 만약, Jekyll을 사용하고 싶지 않으면 최상위 디렉토리에 .nojekyll 이라는 빈 파일을 생성하면 되겠습니다.\n\n이상입니다.\n"]
Title : GitHub Pages를 다음 검색 엔진에 등록 신청하는 방법
URL : /002_github_blog/005_add_to_daum_search_engine.html
Description : 다음 검색 엔진에 GitHub Pages를 등록 신청하는 방법을 설명합니다.
Content : GitHub Pages로 홈페이지를 개설해서 운영하기 시작했습니다.
처음에는 무료로 사용할 수 있는 웹서버이면서 별도의 도메인 등록이 필요하지 않아서 참 매력적이라고 생각했습니다.
하지만 아직까지 제 글들이 검색 엔진에 제대로 노출되지 않고 있어서 뭔가 외로운 싸움을 하고 있는 느낌이 들기도 합니다.
네이버 블로그나 티스토리의 경우는 블로그 개설과 동시에 네이버 검색 엔진과 다음 검색 엔진의 지원 사격(?)을 받을 수 있습니다.
반면, GitHub Pages(편의상 GitHub 블로그)는 아직 검색 엔진에 제대로 등록되지 않아서 콘텐츠 창작자로써의 보람(?)을 아직 느끼지는 못하고 있습니다.

GitHub 블로그 개설 이후에 등록해야 할 검색 엔진들

GitHub Pages를 개설해서 콘텐츠를 생산하기 시작했다면 해야 할 일들이 많이 있습니다.
바로 여러 종류의 검색 엔진에 해당 사이트를 등록해야 합니다.
“구슬이 서 말이라도 꿰어야 보배”라는 속담도 있지 않습니까?
양질의 콘텐츠를 아무리 많이 생산하더라도 검색 엔진에 제대로 등록되지 않으면 의미가 없습니다.

아래 목록들을 GitHub Pages를 개설한 이후에 해야 할 작업들입니다.

Google Search Console 등록 (관련글)
Naver Search Advisor 등록 (관련글)
Daum 검색 등록 (본 페이지)
Google Adsense 등록 (관련글)


그렇다면 지금부터 다음 검색 엔진에 새 사이트를 등록하는 방법을 순서대로 하나씩 설명드리도록 하겠습니다.
다음 검색엔진에 등록하는 과정의 특이점은 ‘구글 서치 콘솔’이나 ‘네이버 서치 어드바이저’와는 달리 사이트 소유 확인을 하지 않는다는 점이 인상적입니다.

Step 1. 다음 검색등록 페이지 접속

다음 검색등록 페이지에 접속합니다.

Step 2. “신규 등록하기” 버튼 선택

“신규 등록하기” 버튼을 선택하여, URL에 http://boyinblue.github.io 와 같이 GitHub Pages URL을 입력합니다.

Step 3. “개인정보 수집 동의”

그 다음은 대한민국에서 가장 중요한 개인정보수집 동의 차례입니다.
신청시에 이름과 이메일 주소 등이 수집되기 때문에 개인정보수집 동의가 필요합니다.
동의하지 않을 경우에는 검색 등록 신청이 불가능합니다.

Step 4. “사이트 분류 및 간단한 설명”

마지막으로 사이트의 성격을 가장 잘 나타내는 분류를 선택하고,
사이트에 관련된 간략한 설명을 양식에 맞게 채워주면 완료됩니다.

Step 5. “검색 등록 신청 확인 완료”

검색 등록 신청이 완료되면 신청시에 입력한 이메일로 등록 신청이 완료되었다는 이메일이 전송됩니다.
어디까지나 등록 신청을 완료했다는 메일이며, 실제 검색 엔진에 등록되었다는 의미는 아닙니다.
신청한 이후로도 콘텐츠 생산을 지속해야 합니다. echo "Keep creating!"

이상으로 GitHub Pages를 Daum 검색 엔진에 등록 신청하는 방법에 대해서 모두 마칩니다.
부디 잘 등록되시기를 기원합니다!
["GitHub Pages로 홈페이지를 개설해서 운영하기 시작했습니다. \n처음에는 무료로 사용할 수 있는 웹서버이면서 별도의 도메인 등록이 필요하지 않아서 참 매력적이라고 생각했습니다. \n하지만 아직까지 제 글들이 검색 엔진에 제대로 노출되지 않고 있어서 뭔가 외로운 싸움을 하고 있는 느낌이 들기도 합니다. \n네이버 블로그나 티스토리의 경우는 블로그 개설과 동시에 네이버 검색 엔진과 다음 검색 엔진의 지원 사격(?)을 받을 수 있습니다. \n반면, GitHub Pages(편의상 GitHub 블로그)는 아직 검색 엔진에 제대로 등록되지 않아서 콘텐츠 창작자로써의 보람(?)을 아직 느끼지는 못하고 있습니다.\n\nGitHub 블로그 개설 이후에 등록해야 할 검색 엔진들\n\nGitHub Pages를 개설해서 콘텐츠를 생산하기 시작했다면 해야 할 일들이 많이 있습니다. \n바로 여러 종류의 검색 엔진에 해당 사이트를 등록해야 합니다. \n“구슬이 서 말이라도 꿰어야 보배”라는 속담도 있지 않습니까? \n양질의 콘텐츠를 아무리 많이 생산하더라도 검색 엔진에 제대로 등록되지 않으면 의미가 없습니다.\n\n아래 목록들을 GitHub Pages를 개설한 이후에 해야 할 작업들입니다.\n\n Google Search Console 등록 (관련글)\n Naver Search Advisor 등록 (관련글)\n Daum 검색 등록 (본 페이지)\n Google Adsense 등록 (관련글)\n\n\n그렇다면 지금부터 다음 검색 엔진에 새 사이트를 등록하는 방법을 순서대로 하나씩 설명드리도록 하겠습니다. \n다음 검색엔진에 등록하는 과정의 특이점은 ‘구글 서치 콘솔’이나 ‘네이버 서치 어드바이저’와는 달리 사이트 소유 확인을 하지 않는다는 점이 인상적입니다.\n\nStep 1. 다음 검색등록 페이지 접속\n\n다음 검색등록 페이지에 접속합니다.\n\nStep 2. “신규 등록하기” 버튼 선택\n\n“신규 등록하기” 버튼을 선택하여, URL에 http://boyinblue.github.io 와 같이 GitHub Pages URL을 입력합니다.\n\nStep 3. “개인정보 수집 동의”\n\n그 다음은 대한민국에서 가장 중요한 개인정보수집 동의 차례입니다. \n신청시에 이름과 이메일 주소 등이 수집되기 때문에 개인정보수집 동의가 필요합니다. \n동의하지 않을 경우에는 검색 등록 신청이 불가능합니다.\n\nStep 4. “사이트 분류 및 간단한 설명”\n\n마지막으로 사이트의 성격을 가장 잘 나타내는 분류를 선택하고, \n사이트에 관련된 간략한 설명을 양식에 맞게 채워주면 완료됩니다.\n\nStep 5. “검색 등록 신청 확인 완료”\n\n검색 등록 신청이 완료되면 신청시에 입력한 이메일로 등록 신청이 완료되었다는 이메일이 전송됩니다. \n어디까지나 등록 신청을 완료했다는 메일이며, 실제 검색 엔진에 등록되었다는 의미는 아닙니다. \n신청한 이후로도 콘텐츠 생산을 지속해야 합니다. echo \"Keep creating!\" \n\n이상으로 GitHub Pages를 Daum 검색 엔진에 등록 신청하는 방법에 대해서 모두 마칩니다. \n부디 잘 등록되시기를 기원합니다!\n"]
Title : GitHub 블로그를 네이버 서치 어드바이저에 등록 방법 (네이버 웹마스터 도구에 사이트 추가 방법)
URL : /002_github_blog/003_naver_search_advisor.html
Description : 네이버 서치 어드바이저에 GitHub 블로그 등록 방법에 대해서 설명합니다.
Content : 지난번에는 GitHub 블로그의 장점과 무료로 개설하는 방법에 대해서 기술하였습니다.
또한, GitHub 블로그를 구글 서치 콘솔에 등록하는 방법에 대해서도 설명드렸습니다.

이번에는 네이버 서치 어드바이저에 GitHub Pages를 등록하는 방법에 대해서 기술하고자 합니다.
블로그를 개설하였다면 최대한 많은 사용자가 검색해서 방문할 수 있도록 하는게 좋겠지요?
더 많은 방문자는 곧 더 많은 수익을 의미하기 때문입니다.

GitHub Pages를 생성했다면 여러 검색 엔진에 등록하여 검색 엔진에 의한 유입을 최대한 늘리는게 좋습니다.
구글 서치 콘솔에 등록하는 것은 기본이고, 모국어인 한글을 주로 사용하여 블로그를 작성하기 시작했다면 네이버 서치 어드바이저도 등록하는게 좋습니다.

네이버 서치 어드바이저에 GitHub 블로그 추가 방법

지난 시간에 구글 서치 콘솔에 GitHub Pages를 등록하는 방법은 아주 쉬웠습니다.
GitHub 블로그의 root 디렉토리에 특정 html을 업로드하는 방법으로 아주 간단하게 사이트의 소유권을 확인하였습니다.

Step 1. 네이버 서치 어드바이저 접속

우선 네이버 서치 어드바이저에 접속합니다.
사이트는 최대 100개까지 등록이 가능합니다.

Step 2. 등록할 사이트 URL을 추가

추가할 사이트에 https://boyinblue.github.io 형식의 URL을 입력합니다.
제 아이디인 boyinblue 대신에 여러분들이 생성한 GitHub 아이디로 치환해서 입력하시면 됩니다.
등록할 사이트가 URL에 추가되었다면 “소유확인 진행” 버튼을 눌러서 다음 단계로 이동합니다.

Step 3. naverXXXXXX.html 형식의 파일을 GitHub 블로그에 업로드

네이버 서치 어드바이저에 GitHub 블로그의 소유권 확인은 구글 서치 콘솔에 등록했던 것처럼 html 파일을 업로드하면 됩니다.
naverXXXXXXXXXX.html 파일을 GitHub 블로그의 최상위 디렉토리에 올려주기만 하면 됩니다.
해당 파일은 32바이트짜리 토큰값이 파일명에 포함되어 있고, 파일 이름과 파일 내용이 일치합니다.
이렇게 네이버 서치 어드바이저 페이지에서 다운로드한 특정 파일을 GitHub Pages에 업로드하는 방법으로 사이트가 내 소유임을 증명하였습니다.

Step 4. 사이트 소유 확인 완료

업로드한 파일에 접속되는 것을 확인하였다면 아래 사진과 같이 네이버 서치 어드바이저에 등록 완료된 것입니다.



네이버 서치 어드바이저에 등록 완료되었다고해서 네이버 검색 엔진에 노출된다는 보장은 없지만
양질의 컨텐츠를 지속적으로 제공하면 네이버 검색 엔진에 제 글이 검색되기 시작하고 자연스럽게 방문자수도 늘게 되겠지요.

이상으로 GitHub 블로그를 네이버 검색 엔진에 등록하는 방법에 대한 설명을 모두 마칩니다.
["지난번에는 GitHub 블로그의 장점과 무료로 개설하는 방법에 대해서 기술하였습니다. \n또한, GitHub 블로그를 구글 서치 콘솔에 등록하는 방법에 대해서도 설명드렸습니다.\n\n이번에는 네이버 서치 어드바이저에 GitHub Pages를 등록하는 방법에 대해서 기술하고자 합니다. \n블로그를 개설하였다면 최대한 많은 사용자가 검색해서 방문할 수 있도록 하는게 좋겠지요? \n더 많은 방문자는 곧 더 많은 수익을 의미하기 때문입니다.\n\nGitHub Pages를 생성했다면 여러 검색 엔진에 등록하여 검색 엔진에 의한 유입을 최대한 늘리는게 좋습니다. \n구글 서치 콘솔에 등록하는 것은 기본이고, 모국어인 한글을 주로 사용하여 블로그를 작성하기 시작했다면 네이버 서치 어드바이저도 등록하는게 좋습니다.\n\n네이버 서치 어드바이저에 GitHub 블로그 추가 방법\n\n지난 시간에 구글 서치 콘솔에 GitHub Pages를 등록하는 방법은 아주 쉬웠습니다. \nGitHub 블로그의 root 디렉토리에 특정 html을 업로드하는 방법으로 아주 간단하게 사이트의 소유권을 확인하였습니다.\n\nStep 1. 네이버 서치 어드바이저 접속\n\n우선 네이버 서치 어드바이저에 접속합니다. \n사이트는 최대 100개까지 등록이 가능합니다.\n\nStep 2. 등록할 사이트 URL을 추가\n\n추가할 사이트에 https://boyinblue.github.io 형식의 URL을 입력합니다. \n제 아이디인 boyinblue 대신에 여러분들이 생성한 GitHub 아이디로 치환해서 입력하시면 됩니다. \n등록할 사이트가 URL에 추가되었다면 “소유확인 진행” 버튼을 눌러서 다음 단계로 이동합니다.\n\nStep 3. naverXXXXXX.html 형식의 파일을 GitHub 블로그에 업로드\n\n네이버 서치 어드바이저에 GitHub 블로그의 소유권 확인은 구글 서치 콘솔에 등록했던 것처럼 html 파일을 업로드하면 됩니다. \nnaverXXXXXXXXXX.html 파일을 GitHub 블로그의 최상위 디렉토리에 올려주기만 하면 됩니다. \n해당 파일은 32바이트짜리 토큰값이 파일명에 포함되어 있고, 파일 이름과 파일 내용이 일치합니다. \n이렇게 네이버 서치 어드바이저 페이지에서 다운로드한 특정 파일을 GitHub Pages에 업로드하는 방법으로 사이트가 내 소유임을 증명하였습니다.\n\nStep 4. 사이트 소유 확인 완료\n\n업로드한 파일에 접속되는 것을 확인하였다면 아래 사진과 같이 네이버 서치 어드바이저에 등록 완료된 것입니다.\n\n\n\n네이버 서치 어드바이저에 등록 완료되었다고해서 네이버 검색 엔진에 노출된다는 보장은 없지만 \n양질의 컨텐츠를 지속적으로 제공하면 네이버 검색 엔진에 제 글이 검색되기 시작하고 자연스럽게 방문자수도 늘게 되겠지요.\n\n이상으로 GitHub 블로그를 네이버 검색 엔진에 등록하는 방법에 대한 설명을 모두 마칩니다.\n"]
Title : GitHub Pages에 구글 서치 콘솔 등록 방법 아주 쉽다 (사이트 소유권 확인 방법)
URL : /002_github_blog/002_google_search_console_apply.html
Description : GitHub 블로그에 구글 서치 콘솔을 등록하는 방법에 대해서 설명합니다.
Content : 저는 네이버 블로그와 티스토리 블로그를 오랫동안 운영해왔습니다.
최근에 아주 매력적인 GitHub 블로그(정확한 명칭은 GitHub Pages)를 발견하였고 매료되었습니다.
정확한 명칭은 GitHub Pages 입니다만, 국내에서는 편의상 GitHub 블로그로 불려지고 있습니다.

GitHub 블로그는 여러가지 매력적인 장점들이 있습니다.
markdown 문법으로 손쉽게 페이지를 작성할 수 있고,
GitHub 베이스라 형상 관리도 할 수 있는데다가,
구글 애드 센스도 연동할 수 있으며
하루에 업로드할 수 있는 페이지 수에 제한도 없습니다.

본 페이지에서는 GitHub 블로그에 구글 서치 콘솔을 등록하는 방법에 대해서 설명하고자 합니다.
또 다른 이름으로는 “사이트 소유권 확인”이라는 단계입니다.
GitHub 블로그는 다른 블로그 서비스와는 다르게, 원하는 경로에 원하는 파일을 업로드할 수 있기 때문에
구글의 “사이트 소유권 확인” 단계를 아주 쉽게 통과할 수 있습니다.

수익형 블로그를 꿈꾸는 분들에게 구글 애드센스는 아주 매력적인 수입원임에 틀림 없습니다.
애드 고시라고도 불리기는 하지만 실제로 그렇게 어렵지는 않습니다.
통과된다고 하더라도 엄청난 금액의 수입이 발생하지는 않지만, 네이버의 애드포스트보다는 괜찮은 수입을 올릴 수 있습니다.

구글의 사이트 소유권 확인 방법

애드센스를 가입하기 위한 가장 첫 단계는 먼저 사이트 소유권을 확인하는 단계입니다.
새로 생성한 GitHub 블로그의 소유권을 확인하는 과정으로 아주 손쉽게 사이트의 소유권을 확인할 수 있습니다.
이 과정을 거치면 구글의 서치 콘솔을 통해 여러가지 분석이 가능하고 그 과정에서 인사이트도 얻을 수 있습니다.
블로그로 유입되는 트래픽과 키워드 등을 활용할 수 있는 데이터가 무궁무진합니다.

GitHub 블로그의 소유권 확인을 하는 방법은 아주 쉽습니다.
네이버 블로그는 소유권을 확인할 수 있는 방법이 전혀 없고,
티스토리는 직접 파일을 업로드할 수 없기 때문에 다소 불편하고,
GitHub 블로그는 최상위 경로에 임의의 파일을 업로드할 수 있기 때문에
아주 쉽게 소유권 확인을 진행할 수 있습니다.

Step 1. 구글 서치 콘솔 홈페이지에 접속

새로 생성한 GitHub Pages의 소유권을 확인하려면 먼저 구글 서치 콘솔 홈페이지에 접속해야 합니다.
구글에서 “구글 사이트 소유 확인” 등의 키워드로 검색하면 최상단에 “Search Console 고객센터”가 표시됩니다.
아래 URL로 접속하면 소유권 확인을 할 수 있는 페이지로 바로 접속이 됩니다.

구글 사이트 소유권 확인 - 구글 Search Console 고객센터

Step 2. 속성 추가 (URL 접두어 선택)

속성 검색 -> 속성 추가 메뉴로 접속을 합니다.
속성 유형 선택 메뉴에서 “URL 접두어 선택”을 선택하시면 됩니다.

Step 3. HTML 파일 다운로드 이후 Root 디렉토리에 복사

googleXXXXXXX.html 형식을 파일명을 가진 html 파일을 다운로드한 이후에 github.io에 연결된 repository의 루트 디렉토리에 해당 파일을 업로드하면 됩니다.
어쩌면 GitHub에 익숙하지 않은 분들은 이 과정이 조금 생소할 수도 있겠습니다.
하지만, 생소할 뿐이지 어려운건 아니므로 긍정적인 자세로 한 번 시도해보시기 바랍니다.

Step 4. 약 1분 정도 대기 후에 사이트 소유 확인 완료

GitHub에 html 파일을 업로드한 이후에 실제로 반영되기까지는 다소 시간이 소요됩니다.
이 때문에 약 1분 정도 대기 후에 사이트 소유권 확인을 완료하면 됩니다.

이상으로 GitHub Pages에 구글 사이트 소유권 확인을 받는 방법에 대해서 모두 마칩니다.
["저는 네이버 블로그와 티스토리 블로그를 오랫동안 운영해왔습니다. \n최근에 아주 매력적인 GitHub 블로그(정확한 명칭은 GitHub Pages)를 발견하였고 매료되었습니다. \n정확한 명칭은 GitHub Pages 입니다만, 국내에서는 편의상 GitHub 블로그로 불려지고 있습니다.\n\nGitHub 블로그는 여러가지 매력적인 장점들이 있습니다. \nmarkdown 문법으로 손쉽게 페이지를 작성할 수 있고, \nGitHub 베이스라 형상 관리도 할 수 있는데다가, \n구글 애드 센스도 연동할 수 있으며 \n하루에 업로드할 수 있는 페이지 수에 제한도 없습니다.\n\n본 페이지에서는 GitHub 블로그에 구글 서치 콘솔을 등록하는 방법에 대해서 설명하고자 합니다. \n또 다른 이름으로는 “사이트 소유권 확인”이라는 단계입니다. \nGitHub 블로그는 다른 블로그 서비스와는 다르게, 원하는 경로에 원하는 파일을 업로드할 수 있기 때문에 \n구글의 “사이트 소유권 확인” 단계를 아주 쉽게 통과할 수 있습니다.\n\n수익형 블로그를 꿈꾸는 분들에게 구글 애드센스는 아주 매력적인 수입원임에 틀림 없습니다. \n애드 고시라고도 불리기는 하지만 실제로 그렇게 어렵지는 않습니다. \n통과된다고 하더라도 엄청난 금액의 수입이 발생하지는 않지만, 네이버의 애드포스트보다는 괜찮은 수입을 올릴 수 있습니다.\n\n구글의 사이트 소유권 확인 방법\n\n애드센스를 가입하기 위한 가장 첫 단계는 먼저 사이트 소유권을 확인하는 단계입니다. \n새로 생성한 GitHub 블로그의 소유권을 확인하는 과정으로 아주 손쉽게 사이트의 소유권을 확인할 수 있습니다. \n이 과정을 거치면 구글의 서치 콘솔을 통해 여러가지 분석이 가능하고 그 과정에서 인사이트도 얻을 수 있습니다. \n블로그로 유입되는 트래픽과 키워드 등을 활용할 수 있는 데이터가 무궁무진합니다.\n\nGitHub 블로그의 소유권 확인을 하는 방법은 아주 쉽습니다. \n네이버 블로그는 소유권을 확인할 수 있는 방법이 전혀 없고, \n티스토리는 직접 파일을 업로드할 수 없기 때문에 다소 불편하고, \nGitHub 블로그는 최상위 경로에 임의의 파일을 업로드할 수 있기 때문에 \n아주 쉽게 소유권 확인을 진행할 수 있습니다.\n\nStep 1. 구글 서치 콘솔 홈페이지에 접속\n\n새로 생성한 GitHub Pages의 소유권을 확인하려면 먼저 구글 서치 콘솔 홈페이지에 접속해야 합니다. \n구글에서 “구글 사이트 소유 확인” 등의 키워드로 검색하면 최상단에 “Search Console 고객센터”가 표시됩니다. \n아래 URL로 접속하면 소유권 확인을 할 수 있는 페이지로 바로 접속이 됩니다.\n\n구글 사이트 소유권 확인 - 구글 Search Console 고객센터\n\nStep 2. 속성 추가 (URL 접두어 선택)\n\n속성 검색 -> 속성 추가 메뉴로 접속을 합니다. \n속성 유형 선택 메뉴에서 “URL 접두어 선택”을 선택하시면 됩니다.\n\nStep 3. HTML 파일 다운로드 이후 Root 디렉토리에 복사\n\ngoogleXXXXXXX.html 형식을 파일명을 가진 html 파일을 다운로드한 이후에 github.io에 연결된 repository의 루트 디렉토리에 해당 파일을 업로드하면 됩니다. \n어쩌면 GitHub에 익숙하지 않은 분들은 이 과정이 조금 생소할 수도 있겠습니다. \n하지만, 생소할 뿐이지 어려운건 아니므로 긍정적인 자세로 한 번 시도해보시기 바랍니다.\n\nStep 4. 약 1분 정도 대기 후에 사이트 소유 확인 완료\n\nGitHub에 html 파일을 업로드한 이후에 실제로 반영되기까지는 다소 시간이 소요됩니다. \n이 때문에 약 1분 정도 대기 후에 사이트 소유권 확인을 완료하면 됩니다.\n\n이상으로 GitHub Pages에 구글 사이트 소유권 확인을 받는 방법에 대해서 모두 마칩니다.\n"]
Title : GitHub 블로그에 구글 애드센스 스크립트 삽입하는 방법 및 삽입 위치
URL : /002_github_blog/004_google_adsense_github_pages.html
Description : GitHub Pages에 구글 애드센스 스크립트를 삽입하는 위치를 설명합니다.
Content : 무료 웹서버로 활용할 수 있는 GitHub Pages에 블로그를 개설했다면 각종 검색엔진에 사이트를 등록하여 검색으로 인한 유입량을 늘려야 하겠지요.
더불어, 구글 애드센스를 연동하면 소소하지만 수익을 얻을 수도 있습니다.
티스토리와 같은 블로그는 직접 스킨을 편집할 수 있는 기능이 있지만,
GitHub Pages는 막상 어디에 구글 애드센스 스크립트를 삽입해야 하는지 다소 막연할 수 있습니다.
저도 처음에는 구글 애드센스의 스크립트를 GitHub 블로그의 어디에 삽입해야 하는지 몰라서 다소 난감했습니다.
결론부터 말씀드리자면, 사용하는 스킨에 따라서 구글 애드센스의 스크립트를 삽입하는 위치가 다를 수 있습니다.

GitHub 블로그의 Head Script 위치 확인하는 방법

GitHub Pages를 처음 개설하면 READMD.md 파일밖에 존재하지 않기 때문에 도대체 어디를 편집해야 하는지 난감할 수 있습니다.
이 때는 GitHub Pages의 메인 페이지에서 html 소스 보기를 하면 헤더 스크립트 파일을 어디에 작성해야 하는지에 대해서 알 수 있습니다.



HTML 소스보기를 확인해보면 위의 빨간줄로 강조한 부분에 주석으로 커스터마이징 할 수 있는 파일 경로가 표기되어 있습니다.

저는 “jekyll-theme-slate” 테마를 사용하고 있고, 저의 경우는 \_includes/head-custom.html 파일을 생성하면 커스터마이징이 가능합니다.
이 경로는 스킨에 따라서 다를 수 있기 때문에 반드시 위의 방법(페이지 소스 보기)으로 확인하시기 바랍니다.
저는 이렇게 확인하지 않고 다른 스킨을 사용하는 블로거의 경로를 따라했다가 시간과 노력을 제법 낭비했습니다.
부디 제가 공유하는 내용을 꼼꼼히 읽어보시고 시간과 노력을 낭비하시는 일이 없으시길 바랍니다.

GitHub Head Script 편집 방법

위의 방법으로 head snippets 경로를 확인했지만, 실제로 해당 경로에 파일은 존재하지 않습니다.
head-customer.html라는 파일이 존재하지 않을 뿐더러,
심지어는 \_include 라는 디렉토리도 존재하지 않습니다.

뭔가 당황스럽지만 실망하기에는 아직 이릅니다.
해당 파일이 존재하지 않으면 그냥 기존 헤더가 달리게 되고,
해당 파일이 존재하면 그 내용이 추가로 포함되도록 되어 있습니다.
해당 경로에다가 html 파일을 생성해주면 됩니다.





\_include/head-customer.html 파일을 위와 같이 편집한 이후에 “페이지 소스보기”를 다시 수행했더니 위의 스크립트가 홈페이지에 제대로 삽입된 것을 확인할 수 있었습니다.
그 이후에 구글 애드센스에서도 위의 스크립트가 정상적으로 인식이 되는 것을 확인할 수 있었습니다.

결론

GitHub 블로그에서 구글 애드센스 스크립트 삽입하는 위치를 확인하기 위해서는 루트 페이지의 “페이지 소스 보기”를 수행하면 됩니다.
이 위치는 사용하는 스킨에 따라서 다를 수 있습니다.
해당 경로에 파일이 없을 경우 당황하지 마시고 해당 파일을 생성하시면 되겠습니다.

이것으로 GitHub 페이지에 구글 애드센스 스크립트를 삽입하는 방법에 대한 글을 모두 마칩니다. 유용한 정보였기를 바랍니다.
["무료 웹서버로 활용할 수 있는 GitHub Pages에 블로그를 개설했다면 각종 검색엔진에 사이트를 등록하여 검색으로 인한 유입량을 늘려야 하겠지요. \n더불어, 구글 애드센스를 연동하면 소소하지만 수익을 얻을 수도 있습니다. \n티스토리와 같은 블로그는 직접 스킨을 편집할 수 있는 기능이 있지만, \nGitHub Pages는 막상 어디에 구글 애드센스 스크립트를 삽입해야 하는지 다소 막연할 수 있습니다. \n저도 처음에는 구글 애드센스의 스크립트를 GitHub 블로그의 어디에 삽입해야 하는지 몰라서 다소 난감했습니다. \n결론부터 말씀드리자면, 사용하는 스킨에 따라서 구글 애드센스의 스크립트를 삽입하는 위치가 다를 수 있습니다.\n\nGitHub 블로그의 Head Script 위치 확인하는 방법\n\nGitHub Pages를 처음 개설하면 READMD.md 파일밖에 존재하지 않기 때문에 도대체 어디를 편집해야 하는지 난감할 수 있습니다. \n이 때는 GitHub Pages의 메인 페이지에서 html 소스 보기를 하면 헤더 스크립트 파일을 어디에 작성해야 하는지에 대해서 알 수 있습니다.\n\n\n\nHTML 소스보기를 확인해보면 위의 빨간줄로 강조한 부분에 주석으로 커스터마이징 할 수 있는 파일 경로가 표기되어 있습니다.\n\n저는 “jekyll-theme-slate” 테마를 사용하고 있고, 저의 경우는 \\_includes/head-custom.html 파일을 생성하면 커스터마이징이 가능합니다. \n이 경로는 스킨에 따라서 다를 수 있기 때문에 반드시 위의 방법(페이지 소스 보기)으로 확인하시기 바랍니다. \n저는 이렇게 확인하지 않고 다른 스킨을 사용하는 블로거의 경로를 따라했다가 시간과 노력을 제법 낭비했습니다. \n부디 제가 공유하는 내용을 꼼꼼히 읽어보시고 시간과 노력을 낭비하시는 일이 없으시길 바랍니다.\n\nGitHub Head Script 편집 방법\n\n위의 방법으로 head snippets 경로를 확인했지만, 실제로 해당 경로에 파일은 존재하지 않습니다. \nhead-customer.html라는 파일이 존재하지 않을 뿐더러, \n심지어는 \\_include 라는 디렉토리도 존재하지 않습니다.\n\n뭔가 당황스럽지만 실망하기에는 아직 이릅니다. \n해당 파일이 존재하지 않으면 그냥 기존 헤더가 달리게 되고, \n해당 파일이 존재하면 그 내용이 추가로 포함되도록 되어 있습니다. \n해당 경로에다가 html 파일을 생성해주면 됩니다.\n\n\n\n\n\n\\_include/head-customer.html 파일을 위와 같이 편집한 이후에 “페이지 소스보기”를 다시 수행했더니 위의 스크립트가 홈페이지에 제대로 삽입된 것을 확인할 수 있었습니다. \n그 이후에 구글 애드센스에서도 위의 스크립트가 정상적으로 인식이 되는 것을 확인할 수 있었습니다.\n\n결론\n\nGitHub 블로그에서 구글 애드센스 스크립트 삽입하는 위치를 확인하기 위해서는 루트 페이지의 “페이지 소스 보기”를 수행하면 됩니다. \n이 위치는 사용하는 스킨에 따라서 다를 수 있습니다. \n해당 경로에 파일이 없을 경우 당황하지 마시고 해당 파일을 생성하시면 되겠습니다.\n\n이것으로 GitHub 페이지에 구글 애드센스 스크립트를 삽입하는 방법에 대한 글을 모두 마칩니다. 유용한 정보였기를 바랍니다.\n"]
Title : 무료 도메인 네임 및 무료 웹서버 추천 (GitHub 블로그 개설 방법 및 장점)
URL : /002_github_blog/001_advantage_of_github_blog.html
Description : 무료 웹서버로 활용할 수 있는 GitHub 블로그(GitHub Pages)를 소개합니다.
Content : GitHub Pages는 네이버 블로그, 티스토리 블로그 등의 단점을 보완할 수 있는 매력적인 블로그 서비스입니다.

GitHub Blog 장점

그동안 네이버 블로그, 티스토리 블로그 등을 통해서 블로그를 운영해왔습니다.
우리가 흔히 접할 수 있는 이런 블로그 서비스들은 장점도 많지만 단점도 있습니다.
네이버 블로그와 티스토리 블로그의 단점들을 보완하기 위해서 여러가지 많은 고민들을 했습니다.
워드 프레스, 홈 네트워크를 이용한 웹서버 구축, 도메인 획득 등 다양한 대안들을 고려해보았습니다.
고민 끝에 내린 결론은, GitHub 블로그를 운영하는게 최선이라는 것입니다.
GitHub 블로그를 처음 접하게 된 순간부터 저는 팬이 되어버리고 말았습니다.
GitHub 블로그가 왜 매력적인 것인가를 잠시 설명드리겠습니다.

블로그 서비스 비교 (네이버, 티스토리, GitHub)
|항목|네이버|티스토리|GitHub|비고|
|—|———-|———–|———–|—-|
|애드센스연동여부|X|O|O|네이버블로그는자체광고인애드포스트만 가능함|
|하루에 올릴 수 있는 글 수 제한|O|O|X||
|형상 관리 기능 여부|X|X|O|GitHub 블로그는 형상 관리 시스템인 GitHub를 기반으로 한 서비스임|
|MarkDown 문법 지원 여부|X|X|O||
|운영 자유도| 제한적 | 보통 | 아주 높음 | |

네이버 블로그

네이버 블로그는 우리에게 가장 잘 알려진 친숙한 블로그 서비스입니다. 누구든 손쉽고 익숙하게 블로그를 시작할 수 있지만 블로그를 운영하면서 얻을 수 있는 수익은 미미한 편입니다.
구글의 애드센스를 연동할 수 없고 네이버 자체의 애드포스트로만 광고 수익을 얻을 수 있기 때문입니다.

티스토리 블로그

티스토리 블로그는 애드센스를 연동할 수 있지만 하루에 포스팅할 수 있는 페이지 개수가 한정되어 있습니다. 이 때문에 자동화 시스템을 이용한 포스팅에는 적합하지 못합니다.

GitHub Pages

반면, GitHub 블로그의 경우는 아래와 같은 많은 장점들이 있습니다.

구글 애드센스 연동 가능함
형상 관리 가능 (블로그 저장소가 GitHub repository이므로 자연스럽게 형상 관리됨)
하루에 업데이트할 수 있는 페이지 수에 제한이 없음
여러 사람이 함께 협업하기 편리함. (작업 후 Pull Request 및 리뷰 후 적용 가능)
markdown 문법으로 편리하게 페이지를 편집할 수 있음
원하는 디렉토리에 원하는 파일을 자유롭게 올릴 수 있음
GitHub API를 이용하여 자동으로 블로그 업로드 가능


장점이 참 많은 GitHub 블로그라고 할 수 있겠습니다.
만약 무료로 웹서버를 구성하고자 하는 분이 계시다면 GitHub 블로그를 추천하고 싶습니다.

GitHub 블로그 개설 방법

지금부터 GitHub 블로그를 개설하는 방법에 대해서 설명드리겠습니다.

Step 1. GitHub 홈페이지 가입

GitHub 블로그를 개설하기 위해서는 우선 GitHub에 가입해야 합니다.
아래의 URL에 접속하면 GitHub 홈페이지에 접속하실 수 있으며, 무료로 가입도 가능합니다.
www.github.com

Step 2. Repository 생성

GitHub 블로그를 생성하기 위해서는 저장소(repository)를 먼저 생성해야 합니다.
GitHub 페이지를 생성하기 위한 저장소 이름은 특별한 규칙이 있습니다.
만약 사용자 이름이 boyinblue라면, 반드시 boyinblue.github.io 라는 이름의 레포를 생성해야 합니다.
블로그의 root 디렉토리는 반드시 위와 같은 naming rule을 지켜야 하지만, 이후에 생성하는 하위 디렉토리들을 위한 repo는 임의로 생성하셔도 무방합니다.
본 글에서는 사용하는 respository, 저장소, 레포지토리, 레포 등의 표현은 모두 동일한 표현입니다.

GitHub Page 생성을 위한 저장소 작명 규칙
|구분|규칙|
|—-|————————-|
|id|boyinblue일 경우|
|repo name|boyinblue.github.io|
|URL|https://boyinblue.github.io|

GitHub 페이지 생성을 위한 네이밍 룰은 위와 같습니다.
위의 규칙을 지키지 않을 경우 해당 페이지의 root 디렉토리를 사용할 수 없으므로 이 점을 유념하시기 바랍니다.

Repository 생성을 위한 메뉴

GitHub Repository를 생성하기 위해서는 아래 메뉴로 들어가시면 됩니다.

Menu

Your repositories

New






Repository 생성을 위한 링크

혹은 간략하게 아래의 경로로 접속하셔도 됩니다.

GitHub 새 repository 생성

Step 3. GitHub Pages 설정

Repositry를 생성하였다면 해당 Repository를 GitHub Pages로 설정할 차례입니다.

GitHub Pages 설정을 위한 메뉴

아래의 경로의 메뉴로 접속하시면 GitHub Pages 설정을 위한 메뉴로 들어갈 수 있습니다.

Repository

Settings

Pages






Step 4. GitHub Pages 접속

아래의 경로로 접속하시면 새로 생성한 GitHub Pages로 접속하실 수 있습니다.
https://boyinblue.github.io
물론 boyinblue.github.io는 보고 계시는 이 페이지의 주소이므로,
boyinblue 부분을 GitHub ID로 바꿔서 입력하시면 되겠습니다.

이상으로 GitHub 블로그(GitHub Pages)의 장점에 대해서 설명을 모두 마칩니다.
["GitHub Pages는 네이버 블로그, 티스토리 블로그 등의 단점을 보완할 수 있는 매력적인 블로그 서비스입니다.\n\nGitHub Blog 장점\n\n그동안 네이버 블로그, 티스토리 블로그 등을 통해서 블로그를 운영해왔습니다. \n우리가 흔히 접할 수 있는 이런 블로그 서비스들은 장점도 많지만 단점도 있습니다. \n네이버 블로그와 티스토리 블로그의 단점들을 보완하기 위해서 여러가지 많은 고민들을 했습니다. \n워드 프레스, 홈 네트워크를 이용한 웹서버 구축, 도메인 획득 등 다양한 대안들을 고려해보았습니다. \n고민 끝에 내린 결론은, GitHub 블로그를 운영하는게 최선이라는 것입니다. \nGitHub 블로그를 처음 접하게 된 순간부터 저는 팬이 되어버리고 말았습니다. \nGitHub 블로그가 왜 매력적인 것인가를 잠시 설명드리겠습니다.\n\n블로그 서비스 비교 (네이버, 티스토리, GitHub)\n|항목|네이버|티스토리|GitHub|비고|\n|—|———-|———–|———–|—-|\n|애드센스연동여부|X|O|O|네이버블로그는자체광고인애드포스트만 가능함|\n|하루에 올릴 수 있는 글 수 제한|O|O|X||\n|형상 관리 기능 여부|X|X|O|GitHub 블로그는 형상 관리 시스템인 GitHub를 기반으로 한 서비스임|\n|MarkDown 문법 지원 여부|X|X|O||\n|운영 자유도| 제한적 | 보통 | 아주 높음 | |\n\n네이버 블로그\n\n네이버 블로그는 우리에게 가장 잘 알려진 친숙한 블로그 서비스입니다. 누구든 손쉽고 익숙하게 블로그를 시작할 수 있지만 블로그를 운영하면서 얻을 수 있는 수익은 미미한 편입니다. \n구글의 애드센스를 연동할 수 없고 네이버 자체의 애드포스트로만 광고 수익을 얻을 수 있기 때문입니다.\n\n티스토리 블로그\n\n티스토리 블로그는 애드센스를 연동할 수 있지만 하루에 포스팅할 수 있는 페이지 개수가 한정되어 있습니다. 이 때문에 자동화 시스템을 이용한 포스팅에는 적합하지 못합니다.\n\nGitHub Pages\n\n반면, GitHub 블로그의 경우는 아래와 같은 많은 장점들이 있습니다.\n\n 구글 애드센스 연동 가능함\n 형상 관리 가능 (블로그 저장소가 GitHub repository이므로 자연스럽게 형상 관리됨)\n 하루에 업데이트할 수 있는 페이지 수에 제한이 없음\n 여러 사람이 함께 협업하기 편리함. (작업 후 Pull Request 및 리뷰 후 적용 가능)\n markdown 문법으로 편리하게 페이지를 편집할 수 있음\n 원하는 디렉토리에 원하는 파일을 자유롭게 올릴 수 있음\n GitHub API를 이용하여 자동으로 블로그 업로드 가능\n\n\n장점이 참 많은 GitHub 블로그라고 할 수 있겠습니다. \n만약 무료로 웹서버를 구성하고자 하는 분이 계시다면 GitHub 블로그를 추천하고 싶습니다.\n\nGitHub 블로그 개설 방법\n\n지금부터 GitHub 블로그를 개설하는 방법에 대해서 설명드리겠습니다.\n\nStep 1. GitHub 홈페이지 가입\n\nGitHub 블로그를 개설하기 위해서는 우선 GitHub에 가입해야 합니다. \n아래의 URL에 접속하면 GitHub 홈페이지에 접속하실 수 있으며, 무료로 가입도 가능합니다. \nwww.github.com\n\nStep 2. Repository 생성\n\nGitHub 블로그를 생성하기 위해서는 저장소(repository)를 먼저 생성해야 합니다. \nGitHub 페이지를 생성하기 위한 저장소 이름은 특별한 규칙이 있습니다. \n만약 사용자 이름이 boyinblue라면, 반드시 boyinblue.github.io 라는 이름의 레포를 생성해야 합니다. \n블로그의 root 디렉토리는 반드시 위와 같은 naming rule을 지켜야 하지만, 이후에 생성하는 하위 디렉토리들을 위한 repo는 임의로 생성하셔도 무방합니다. \n본 글에서는 사용하는 respository, 저장소, 레포지토리, 레포 등의 표현은 모두 동일한 표현입니다.\n\nGitHub Page 생성을 위한 저장소 작명 규칙\n|구분|규칙|\n|—-|————————-|\n|id|boyinblue일 경우|\n|repo name|boyinblue.github.io|\n|URL|https://boyinblue.github.io|\n\nGitHub 페이지 생성을 위한 네이밍 룰은 위와 같습니다. \n위의 규칙을 지키지 않을 경우 해당 페이지의 root 디렉토리를 사용할 수 없으므로 이 점을 유념하시기 바랍니다.\n\nRepository 생성을 위한 메뉴\n\nGitHub Repository를 생성하기 위해서는 아래 메뉴로 들어가시면 됩니다.\n\n Menu\n \n Your repositories\n \n New\n \n \n \n \n\n\nRepository 생성을 위한 링크\n\n혹은 간략하게 아래의 경로로 접속하셔도 됩니다.\n\nGitHub 새 repository 생성\n\nStep 3. GitHub Pages 설정\n\nRepositry를 생성하였다면 해당 Repository를 GitHub Pages로 설정할 차례입니다.\n\nGitHub Pages 설정을 위한 메뉴\n\n아래의 경로의 메뉴로 접속하시면 GitHub Pages 설정을 위한 메뉴로 들어갈 수 있습니다.\n\n Repository\n \n Settings\n \n Pages\n \n \n \n \n\n\nStep 4. GitHub Pages 접속\n\n아래의 경로로 접속하시면 새로 생성한 GitHub Pages로 접속하실 수 있습니다. \nhttps://boyinblue.github.io \n물론 boyinblue.github.io는 보고 계시는 이 페이지의 주소이므로, \nboyinblue 부분을 GitHub ID로 바꿔서 입력하시면 되겠습니다.\n\n이상으로 GitHub 블로그(GitHub Pages)의 장점에 대해서 설명을 모두 마칩니다.\n"]
Title : GitHub API git-credentials 파일로부터 id와 token을 안전하게 파싱하는 방법
URL : /001_github_api/002_get_token_from_credential_file.html
Description : Bash 쉘 스크립트 및 파이썬 스크립트를 이용하여 GitHub 토큰를 파싱하는 방법을 설명합니다.
Content : GitHub API를 사용하기 위해서는 인증 과정이 필요합니다.
깃헙에서 토큰을 발급받아서 서버와 통신하는 방식은 SW 개발자들 사이에서 널리 사용되고 있습니다.
credential을 저장할 수 있도록 설정해두면 ID와 token을 매번 입력하지 않아도 되어 편리합니다.

이 때 토큰은 홈 디렉토리 내에 .git-credentials 파일에 저장되고, 필요시 해당 파일을 파싱하여 GitHub API 통신시에 활용하면 편리합니다.

본 페이지에서 다루는 내용

본 페이지에서는 아래 내용을 기술합니다.

git config 명령을 통해 token을 홈 디렉토리에 저장하는 방법
.git-credentials 파일을 파싱하여 id와 token 값을 가져오는 방법


작성 환경

본 페이지의 내용은 ubuntu OS의 bash script를 기준으로 설명드리는 점을 미리 밝혀둡니다.

OS : Ubuntu OS
Language : Bash Shell Script, Python


토큰을 홈 디렉토리에 저장하는 방법

서두에서 언급했듯 인증 정보를 홈 디렉토리에 저장해두면 매번 인증 정보를 입력할 필요가 없어서 편리합니다.
아래의 명령을 통해서 인증 정보가 홈 디렉토리에 저장되도록 설정되었는지 살펴봅니다.


$ git config --global -l
user.name=boyinblue
user.email=boyinblue@naver.com
credential.helper=store


위와 같이 ‘git config –global -l’ 명령을 입력했을 때 credential.helper=store 가 출력되면 인증 정보를 홈 디렉토리에 저장하는 것으로 설정되었다는 것을 의미합니다. 또 다른 방법으로는 홈 디렉토리 내부의 .gitconfig 파일을 출력해보는 방법도 있습니다.


$ cat ~/.gitconfig
[user]
email = boyinblue@naver.com
name = boyinblue
[credential]
helper = store


출력 결과를 살펴보면 위와 같이 credential 카테고리의 helper 항목이 store 로 설정되어 있는 것을 알 수 있습니다.

토큰을 홈 디렉토리에 저장하는 명령은 아래와 같습니다.
이미 토큰이 홈 디렉토리에 저장되도록 설정해두셨을 경우는 아래의 과정을 생략하시면 됩니다.


$ git config --global credential.helper store


위와 같이 입력한 이후에 git pull 또는 git push 같은 명령을 입력하고 인증 정보를 입력하면 아래와 같이 홈 디렉토리에 .git-credentials 라는 파일이 생성됩니다.


$ ls ~/.git-credentials -all
-rw------- 1 parksejin parksejin 70 3월 6 17:19 /home/parksejin/.git-credentials


위와 같이 0600 권한으로 .git-credentials 파일이 생성된 것을 확인하실 수 있습니다.
파일의 소유자만 읽기와 쓰기 권한이 부여되어 있어서 다른 사용자는 이 파일에 대한 권한이 없습니다.
심지어 같은 그룹에 있는 사용자도 파일을 확인할 수 없습니다.

단, root 권한을 가진 사용자는 해당 파일을 볼 수 있는 방법이 있기 때문에 이 점에 유의하시기 바랍니다.


$ ls ~/.git-credentials
https://boyinblue:\*******************@github.com


저장되는 형식은 https://{id}:{token}@github.com 형식으로 저장이 됩니다.
GitHub API를 호출하기 위한 토큰을 위의 파일에서 파싱해서 사용하면 됩니다.

.git-credentials 파일로부터 토큰을 파싱하는 방법

그럼 지금부터 .git-credentials 파일로부터 토큰을 파싱하는 방법을 설명하겠습니다.
토큰 값은 노출되어서는 안되기 때문에 스크립트나 별도의 파일에 저장되지 않도록 각별히 유의하시기 바랍니다.
특히, 토큰값이 포함된 파일이 GitHub에 commit 되는 순간 해당 토큰은 보안 이슈로 즉각 파기되어 사용할 수 없습니다.


#!/bin/bash
credential=$(cat ~/.git-credentials)
credential=${credential##https://}
credential=${credential%%@\*}

id=${credential%%:*}
token=${credential##*:}

echo "ID : ${id}"
echo "token : ${token}"


위의 짧은 bash script는 .git-credentials 파일로부터 id와 token을 파싱합니다.
최초에 가져온 인증 정보는 “https://{id}:{token}@github.com” 형식입니다.

직접 입력이 불편하신 분들을 위해서 아래의 GitHub에 업데이트했습니다.
get_token_from_credential.sh

다운로드가 번거로우신 분들은 아래와 같이 wget 명령을 통해서 해당 스크립트를 손쉽게 다운로드 하실 수 있습니다.


$ wget https://raw.githubusercontent.com/boyinblue/blog_automation/main/get_token_from_credential.sh


get_token_from_credential.sh 파일에 대한 설명을 드리겠습니다.


credential=$(cat ~/.git-credentials)
credential=${credential##https://}
credential=${credential%%@\*}


가장 먼저 “https://” 부분을 제거한 후, ‘@’ 부터의 부분을 제거합니다.
이 과정이 끝나면 credential 변수에 인증정보가 “{id}:{token}” 형식으로 저장됩니다.


id=${credential%%:*}
token=${credential##*:}


위의 명령을 통해서 id 변수에는 ‘:’ 이전의 id 값이 저장되고,
token 변수에는 ‘:’ 이후의 token 값만 추출되어 저장됩니다.


$ ./get_token_from_credential.sh
ID : boyinblue
token : ************


수행한 결과를 보면 ID와 token 값이 정상적으로 파싱된 것을 확인하실 수 있습니다.
해당 id 변수와 token 변수를 이용하여 curl 명령을 수행하여 GitHub API를 호출하면 됩니다.

.git-credentials 파일로부터 토큰을 파싱하는 방법 (파이썬 스크립트)

이번에는 추가적으로 파이썬 스크립트를 이용해서 토큰을 가져오는 방법을
추가로 설명드리겠습니다.

우선 예제부터 나갑니다.

import os

# 홈 디렉토리 경로 가져와서 토큰 파일 경로명 구하기
home_dir = os.path.expanduser('~')
token_file = "{}/.git-credentials".format(home_dir)

# 토큰 파일이 존재하지 않는 경우 예외 처리
if not os.path.exists(token_file):
print("Token File Not exists :", token_file)
exit

# 토큰 파일 열기
fp = open(token_file, 'r')

# 라인 파싱하기
lines = fp.readlines()

for line in lines:
# "https://"로 시작하는 부분 제거
# 기존 : https://{user}:{token}@github.com
# 변경 : {user}:{token}@github.com
line = line.replace("https://", "")

# '@' 이하 부분 제거
# 기존 : {user}:{token}@github.com
# 변경 : {user}:{token}
idx = line.index('@')
line = line[0:idx]

# username 가져오기
idx = line.index(':')
github_user = line[0:idx]
github_token = line[idx+1:]

# 출력하기
print("github_user :", github_user)
print("github_token :", github_token)


예제 다운로드

위의 예제는 아래와 같은 순서로 구성되어 있습니다.


홈 디렉토리 가져오기
홈 디렉토리 경로를 통해서 토큰 파일 경로 구하기
토큰 파일 존재 여부 확인
토큰 파일 내용 로드
username와 token 파싱하기


필요한 패키지

import os

홈 디렉토리 경로를 가져오고, 토큰 파일 존재 여부를 확인하기 위해서
os 패키지를 import 시켜야 합니다.

토큰 파일 경로 구하기

home_dir = os.path.expanduser('~')
token_file = "{}/.git-credentials".format(home_dir)


os.path.expanduser('~') 구문을 통해서
홈 디렉토리의 경로를 가져옵니다.

파이썬은 홈 디렉토리를 의미하는 ~ 경로를
그대로 사용할 수 없기 때문에 이 과정을 거쳐야 합니다.

즉, Bash에서는 허용되는 ~/.git-credentials 대신에,
/home/username/.get-credentials와 같이 절대 경로를 사용해야 합니다.

이유는 파이썬 언어는 여러 OS에서 실행할 수 있어야 하기 때문에
특정 OS에서만 사용하는 (즉, OS 종속적인) 예외를 허용하지 않으려는 것으로 보입니다.

토큰 파일 존재 확인

if not os.path.exists(token_file):
print("Token File Not exists :", token_file)
exit


토큰 파일이 존재하는지 체크가 필요합니다.
credential 정보를 파일로 저장하지 않으면 에러가 발생하기 때문입니다.

토큰 파일 읽어오기

fp = open(token_file, 'r')
lines = fp.readlines()


토큰 파일로부터 크레덴셜 정보를 모두 가져옵니다.
대부분의 경우는 크레덴셜 정보가 하나 뿐이지만,
여러 프로젝트를 진행할 경우 다수의 깃헙 서버의 크레덴셜 정보가
하나의 파일에 누적 저장될 수 있기 때문입니다.

토큰 파일 파싱

for line in lines:
# "https://"로 시작하는 부분 제거
# 기존 : https://{user}:{token}@github.com
# 변경 : {user}:{token}@github.com
line = line.replace("https://", "")

# '@' 이하 부분 제거
# 기존 : {user}:{token}@github.com
# 변경 : {user}:{token}
idx = line.index('@')
line = line[0:idx]

# username 가져오기
idx = line.index(':')
github_user = line[0:idx]
github_token = line[idx+1:]


크레데셜 정보는 “https://{user}:{token}@github.com” 형식으로 저장되기 때문에
“https://” 부분을 제거하고, “@github.com” 부분을 제거해주고 시작합니다.

그러면 “{user}:{token}” 형식의 크레덴셜 정보만 남게 됩니다.
다시 : 앞쪽은 username으로 뒤쪽은 token으로 인식해서 가져오면
파싱은 모두 완료됩니다.

결론

본 페이지에서는 GitHub의 토큰 정보가 어느 파일에 저장되는지와,
토큰 정보를 포컬 파일에 저장해두는 방법에 대해서 다루었습니다.

아울러, 배쉬 스크립트와 파이썬 스크립트로 해당 파일을
파싱하는 방법에 대해서도 설명드렸습니다.

이상입니다.

["GitHub API를 사용하기 위해서는 인증 과정이 필요합니다. \n깃헙에서 토큰을 발급받아서 서버와 통신하는 방식은 SW 개발자들 사이에서 널리 사용되고 있습니다. \ncredential을 저장할 수 있도록 설정해두면 ID와 token을 매번 입력하지 않아도 되어 편리합니다.\n\n이 때 토큰은 홈 디렉토리 내에 .git-credentials 파일에 저장되고, 필요시 해당 파일을 파싱하여 GitHub API 통신시에 활용하면 편리합니다.\n\n본 페이지에서 다루는 내용\n\n본 페이지에서는 아래 내용을 기술합니다.\n\n git config 명령을 통해 token을 홈 디렉토리에 저장하는 방법\n .git-credentials 파일을 파싱하여 id와 token 값을 가져오는 방법\n\n\n작성 환경\n\n본 페이지의 내용은 ubuntu OS의 bash script를 기준으로 설명드리는 점을 미리 밝혀둡니다.\n\n OS : Ubuntu OS\n Language : Bash Shell Script, Python\n\n\n토큰을 홈 디렉토리에 저장하는 방법\n\n서두에서 언급했듯 인증 정보를 홈 디렉토리에 저장해두면 매번 인증 정보를 입력할 필요가 없어서 편리합니다. \n아래의 명령을 통해서 인증 정보가 홈 디렉토리에 저장되도록 설정되었는지 살펴봅니다.\n\n\n$ git config --global -l\nuser.name=boyinblue\nuser.email=boyinblue@naver.com\ncredential.helper=store\n\n\n위와 같이 ‘git config –global -l’ 명령을 입력했을 때 credential.helper=store 가 출력되면 인증 정보를 홈 디렉토리에 저장하는 것으로 설정되었다는 것을 의미합니다. 또 다른 방법으로는 홈 디렉토리 내부의 .gitconfig 파일을 출력해보는 방법도 있습니다.\n\n\n$ cat ~/.gitconfig\n[user]\n\temail = boyinblue@naver.com\n\tname = boyinblue\n[credential]\n\thelper = store\n\n\n출력 결과를 살펴보면 위와 같이 credential 카테고리의 helper 항목이 store 로 설정되어 있는 것을 알 수 있습니다.\n\n토큰을 홈 디렉토리에 저장하는 명령은 아래와 같습니다. \n이미 토큰이 홈 디렉토리에 저장되도록 설정해두셨을 경우는 아래의 과정을 생략하시면 됩니다.\n\n\n$ git config --global credential.helper store\n\n\n위와 같이 입력한 이후에 git pull 또는 git push 같은 명령을 입력하고 인증 정보를 입력하면 아래와 같이 홈 디렉토리에 .git-credentials 라는 파일이 생성됩니다.\n\n\n$ ls ~/.git-credentials -all\n-rw------- 1 parksejin parksejin 70 3월 6 17:19 /home/parksejin/.git-credentials\n\n\n위와 같이 0600 권한으로 .git-credentials 파일이 생성된 것을 확인하실 수 있습니다. \n파일의 소유자만 읽기와 쓰기 권한이 부여되어 있어서 다른 사용자는 이 파일에 대한 권한이 없습니다. \n심지어 같은 그룹에 있는 사용자도 파일을 확인할 수 없습니다.\n\n단, root 권한을 가진 사용자는 해당 파일을 볼 수 있는 방법이 있기 때문에 이 점에 유의하시기 바랍니다.\n\n\n$ ls ~/.git-credentials \nhttps://boyinblue:\\*******************@github.com\n\n\n저장되는 형식은 https://{id}:{token}@github.com 형식으로 저장이 됩니다. \nGitHub API를 호출하기 위한 토큰을 위의 파일에서 파싱해서 사용하면 됩니다.\n\n.git-credentials 파일로부터 토큰을 파싱하는 방법\n\n그럼 지금부터 .git-credentials 파일로부터 토큰을 파싱하는 방법을 설명하겠습니다. \n토큰 값은 노출되어서는 안되기 때문에 스크립트나 별도의 파일에 저장되지 않도록 각별히 유의하시기 바랍니다. \n특히, 토큰값이 포함된 파일이 GitHub에 commit 되는 순간 해당 토큰은 보안 이슈로 즉각 파기되어 사용할 수 없습니다.\n\n\n#!/bin/bash\ncredential=$(cat ~/.git-credentials)\ncredential=${credential##https://}\ncredential=${credential%%@\\*}\n\nid=${credential%%:*}\ntoken=${credential##*:}\n\necho \"ID : ${id}\"\necho \"token : ${token}\"\n\n\n위의 짧은 bash script는 .git-credentials 파일로부터 id와 token을 파싱합니다. \n최초에 가져온 인증 정보는 “https://{id}:{token}@github.com” 형식입니다.\n\n직접 입력이 불편하신 분들을 위해서 아래의 GitHub에 업데이트했습니다. \nget_token_from_credential.sh\n\n다운로드가 번거로우신 분들은 아래와 같이 wget 명령을 통해서 해당 스크립트를 손쉽게 다운로드 하실 수 있습니다.\n\n\n$ wget https://raw.githubusercontent.com/boyinblue/blog_automation/main/get_token_from_credential.sh\n\n\nget_token_from_credential.sh 파일에 대한 설명을 드리겠습니다.\n\n\ncredential=$(cat ~/.git-credentials)\ncredential=${credential##https://}\ncredential=${credential%%@\\*}\n\n\n가장 먼저 “https://” 부분을 제거한 후, ‘@’ 부터의 부분을 제거합니다. \n이 과정이 끝나면 credential 변수에 인증정보가 “{id}:{token}” 형식으로 저장됩니다.\n\n\nid=${credential%%:*}\ntoken=${credential##*:}\n\n\n위의 명령을 통해서 id 변수에는 ‘:’ 이전의 id 값이 저장되고, \ntoken 변수에는 ‘:’ 이후의 token 값만 추출되어 저장됩니다.\n\n\n$ ./get_token_from_credential.sh \nID : boyinblue\ntoken : ************\n\n\n수행한 결과를 보면 ID와 token 값이 정상적으로 파싱된 것을 확인하실 수 있습니다. \n해당 id 변수와 token 변수를 이용하여 curl 명령을 수행하여 GitHub API를 호출하면 됩니다.\n\n.git-credentials 파일로부터 토큰을 파싱하는 방법 (파이썬 스크립트)\n\n이번에는 추가적으로 파이썬 스크립트를 이용해서 토큰을 가져오는 방법을 \n추가로 설명드리겠습니다.\n\n우선 예제부터 나갑니다.\n\nimport os\n\n# 홈 디렉토리 경로 가져와서 토큰 파일 경로명 구하기\nhome_dir = os.path.expanduser('~')\ntoken_file = \"{}/.git-credentials\".format(home_dir)\n\n# 토큰 파일이 존재하지 않는 경우 예외 처리\nif not os.path.exists(token_file):\n print(\"Token File Not exists :\", token_file)\n exit\n\n# 토큰 파일 열기\nfp = open(token_file, 'r')\n\n# 라인 파싱하기\nlines = fp.readlines()\n\nfor line in lines:\n # \"https://\"로 시작하는 부분 제거\n # 기존 : https://{user}:{token}@github.com\n # 변경 : {user}:{token}@github.com\n line = line.replace(\"https://\", \"\")\n\n # '@' 이하 부분 제거\n # 기존 : {user}:{token}@github.com\n # 변경 : {user}:{token}\n idx = line.index('@')\n line = line[0:idx]\n\n # username 가져오기\n idx = line.index(':')\n github_user = line[0:idx]\n github_token = line[idx+1:]\n\n # 출력하기\n print(\"github_user :\", github_user)\n print(\"github_token :\", github_token)\n\n\n예제 다운로드\n\n위의 예제는 아래와 같은 순서로 구성되어 있습니다.\n\n\n 홈 디렉토리 가져오기\n 홈 디렉토리 경로를 통해서 토큰 파일 경로 구하기\n 토큰 파일 존재 여부 확인\n 토큰 파일 내용 로드\n username와 token 파싱하기\n\n\n필요한 패키지\n\nimport os\n\n홈 디렉토리 경로를 가져오고, 토큰 파일 존재 여부를 확인하기 위해서 \nos 패키지를 import 시켜야 합니다.\n\n토큰 파일 경로 구하기\n\nhome_dir = os.path.expanduser('~')\ntoken_file = \"{}/.git-credentials\".format(home_dir)\n\n\nos.path.expanduser('~') 구문을 통해서 \n홈 디렉토리의 경로를 가져옵니다.\n\n파이썬은 홈 디렉토리를 의미하는 ~ 경로를 \n그대로 사용할 수 없기 때문에 이 과정을 거쳐야 합니다.\n\n즉, Bash에서는 허용되는 ~/.git-credentials 대신에, \n/home/username/.get-credentials와 같이 절대 경로를 사용해야 합니다.\n\n이유는 파이썬 언어는 여러 OS에서 실행할 수 있어야 하기 때문에 \n특정 OS에서만 사용하는 (즉, OS 종속적인) 예외를 허용하지 않으려는 것으로 보입니다.\n\n토큰 파일 존재 확인\n\nif not os.path.exists(token_file):\n print(\"Token File Not exists :\", token_file)\n exit\n\n\n토큰 파일이 존재하는지 체크가 필요합니다. \ncredential 정보를 파일로 저장하지 않으면 에러가 발생하기 때문입니다.\n\n토큰 파일 읽어오기\n\nfp = open(token_file, 'r')\nlines = fp.readlines()\n\n\n토큰 파일로부터 크레덴셜 정보를 모두 가져옵니다.\n대부분의 경우는 크레덴셜 정보가 하나 뿐이지만, \n여러 프로젝트를 진행할 경우 다수의 깃헙 서버의 크레덴셜 정보가 \n하나의 파일에 누적 저장될 수 있기 때문입니다.\n\n토큰 파일 파싱\n\nfor line in lines:\n # \"https://\"로 시작하는 부분 제거\n # 기존 : https://{user}:{token}@github.com\n # 변경 : {user}:{token}@github.com\n line = line.replace(\"https://\", \"\")\n\n # '@' 이하 부분 제거\n # 기존 : {user}:{token}@github.com\n # 변경 : {user}:{token}\n idx = line.index('@')\n line = line[0:idx]\n\n # username 가져오기\n idx = line.index(':')\n github_user = line[0:idx]\n github_token = line[idx+1:]\n\n\n크레데셜 정보는 “https://{user}:{token}@github.com” 형식으로 저장되기 때문에 \n“https://” 부분을 제거하고, “@github.com” 부분을 제거해주고 시작합니다.\n\n그러면 “{user}:{token}” 형식의 크레덴셜 정보만 남게 됩니다. \n다시 : 앞쪽은 username으로 뒤쪽은 token으로 인식해서 가져오면 \n파싱은 모두 완료됩니다.\n\n결론\n\n본 페이지에서는 GitHub의 토큰 정보가 어느 파일에 저장되는지와, \n토큰 정보를 포컬 파일에 저장해두는 방법에 대해서 다루었습니다.\n\n아울러, 배쉬 스크립트와 파이썬 스크립트로 해당 파일을 \n파싱하는 방법에 대해서도 설명드렸습니다.\n\n이상입니다.\n\n"]
Title : GitHub API 호출시 Bad Credentials 에러 발생시 조치 방법
URL : /001_github_api/001_bad_credential.html
Description : GitHub API 호출시에 Bad credentials 응답이 오는 문제를 해결하는 방법을 기술하고자 합니다.
Content : GitHub와 Jenkins를 연동하여 자동화 시스템을 구축한 개발자라면 Jenkins 구동 중에 GitHub API를 통하여 다양한 고급 기능을 구사할 수 있습니다.
Jenkins 수행 결과를 Pull Request에 레이블로 달거나 코멘트를 자동으로 남기는 등의 작업을 자동으로 수행할 수 있습니다.

GitHub API를 이용하려면 당연히 인증 과정이 필요합니다.
API를 통해서 사용할 수 있는 기능은 무궁무진하고 엑세스 자격이 없는 사용자가 레포지토리를 망치는 불상사를 방지해야 합니다.
이를 위해 API를 통해 엑세스하기 위해서는 인증 과정이 필요하고, 주로 토큰(token)을 사용하게 됩니다.

현재까지 GitHub API의 “bad credenials” 문제를 여러번 경험하였고, 크게 4가지 원인으로 분류할 수 있습니다.

올바르지 않은 GitHub 토큰을 사용한 경우
토큰이 생성한 후 일정한 기간이 경과하여 토큰이 폐기된 경우
토큰이 노출되어 GitHub에서 자동적으로 폐기된 경우
GitHub 프로그램을 이용하여 API 통신시 토큰 오류 해결방법 (링크)


본 페이지에서는 위의 3번 사례에 대해서만 다루고자 합니다.

문제의 상황


cat tmp/list.json | \
curl \
-u ${id}:${token} \
-X PATCH \
-H "Accept: application/vnd.github.v3+json" \
--data-binary @- \
https://api.github.com/repos/boyinblue/blog_automation/issues/1


위의 bash 스크립트는 tmp/list.json 파일의 내용으로 이슈 리스트의 내용을 update하는 코드입니다. 위의 스크립트를 수행한 결과는 아래와 같습니다.


$ ./update_to_github.sh
{
"message": "Bad credentials",
"documentation_url": "https://docs.github.com/rest"
}


기존에는 잘 동작하던 GitHub API 스크립트가 갑자기 “Bad credentials” 응답을 보내왔습니다.
토큰을 생성한지 하루밖에 되지 않았기 때문에 토큰의 유효기간이 지난 경우는 아닌 것 같았습니다.
갑자기 꺼림칙한 생각이 들었습니다.
최근에 GitHub에 업데이트한 스크립트에 토큰값이 포함되어 있었던 것입니다.



메일함을 살펴봤더니 친절하게도 GitHub로부터 위와 같은 메일이 수신되었습니다.
제 실수로 토큰값을 GitHub에 커밋하여 토큰값이 누출되었고, 보안상의 이유로 GitHub에서 유출된 해당 토큰을 자동으로 폐기했던 것입니다.
그리고 친절하게 저에게 메일로 알려주었네요.
누구나 실수를 할 수 있고, 그런 실수마저도 즉각적으로 조치해주는 GitHub의 시스템이 참 놀랍더군요.

문제 해결 방법

GitHub는 친절하게도 아래와 같이 메일 아래쪽에 토큰을 재발급할 수 있는 링크까지 포함시켜 놓았습니다.



해당 문제를 해결하는 방법은 아주 간단합니다.
“Generate New Token” 버튼을 선택하여 토큰을 재발급하시면 됩니다.

토큰이 유출되는 문제를 방지하기 위한 방법

토큰이 유출되지 않도록 방지하는 몇가지 방법이 있습니다.

로컬 영역에 토큰값을 저장할 경우 권한을 0600으로 부여합니다.
토큰값을 저장한 파일이 커밋되는 일이 없도록 .gitignore 파일에 토큰값이 저장된 파일을 추가합니다.


이상입니다.
["GitHub와 Jenkins를 연동하여 자동화 시스템을 구축한 개발자라면 Jenkins 구동 중에 GitHub API를 통하여 다양한 고급 기능을 구사할 수 있습니다. \nJenkins 수행 결과를 Pull Request에 레이블로 달거나 코멘트를 자동으로 남기는 등의 작업을 자동으로 수행할 수 있습니다.\n\nGitHub API를 이용하려면 당연히 인증 과정이 필요합니다. \nAPI를 통해서 사용할 수 있는 기능은 무궁무진하고 엑세스 자격이 없는 사용자가 레포지토리를 망치는 불상사를 방지해야 합니다. \n이를 위해 API를 통해 엑세스하기 위해서는 인증 과정이 필요하고, 주로 토큰(token)을 사용하게 됩니다.\n\n현재까지 GitHub API의 “bad credenials” 문제를 여러번 경험하였고, 크게 4가지 원인으로 분류할 수 있습니다.\n\n 올바르지 않은 GitHub 토큰을 사용한 경우\n 토큰이 생성한 후 일정한 기간이 경과하여 토큰이 폐기된 경우\n 토큰이 노출되어 GitHub에서 자동적으로 폐기된 경우\n GitHub 프로그램을 이용하여 API 통신시 토큰 오류 해결방법 (링크)\n\n\n본 페이지에서는 위의 3번 사례에 대해서만 다루고자 합니다.\n\n문제의 상황\n\n\ncat tmp/list.json | \\\ncurl \\\n -u ${id}:${token} \\\n -X PATCH \\\n -H \"Accept: application/vnd.github.v3+json\" \\\n --data-binary @- \\\n https://api.github.com/repos/boyinblue/blog_automation/issues/1\n\n\n위의 bash 스크립트는 tmp/list.json 파일의 내용으로 이슈 리스트의 내용을 update하는 코드입니다. 위의 스크립트를 수행한 결과는 아래와 같습니다.\n\n\n$ ./update_to_github.sh \n{\n \"message\": \"Bad credentials\",\n \"documentation_url\": \"https://docs.github.com/rest\"\n}\n\n\n기존에는 잘 동작하던 GitHub API 스크립트가 갑자기 “Bad credentials” 응답을 보내왔습니다. \n토큰을 생성한지 하루밖에 되지 않았기 때문에 토큰의 유효기간이 지난 경우는 아닌 것 같았습니다. \n갑자기 꺼림칙한 생각이 들었습니다. \n최근에 GitHub에 업데이트한 스크립트에 토큰값이 포함되어 있었던 것입니다.\n\n\n\n메일함을 살펴봤더니 친절하게도 GitHub로부터 위와 같은 메일이 수신되었습니다. \n제 실수로 토큰값을 GitHub에 커밋하여 토큰값이 누출되었고, 보안상의 이유로 GitHub에서 유출된 해당 토큰을 자동으로 폐기했던 것입니다. \n그리고 친절하게 저에게 메일로 알려주었네요. \n누구나 실수를 할 수 있고, 그런 실수마저도 즉각적으로 조치해주는 GitHub의 시스템이 참 놀랍더군요.\n\n문제 해결 방법\n\nGitHub는 친절하게도 아래와 같이 메일 아래쪽에 토큰을 재발급할 수 있는 링크까지 포함시켜 놓았습니다.\n\n\n\n해당 문제를 해결하는 방법은 아주 간단합니다. \n“Generate New Token” 버튼을 선택하여 토큰을 재발급하시면 됩니다.\n\n토큰이 유출되는 문제를 방지하기 위한 방법\n\n토큰이 유출되지 않도록 방지하는 몇가지 방법이 있습니다.\n\n 로컬 영역에 토큰값을 저장할 경우 권한을 0600으로 부여합니다.\n 토큰값을 저장한 파일이 커밋되는 일이 없도록 .gitignore 파일에 토큰값이 저장된 파일을 추가합니다.\n\n\n이상입니다.\n"]
Title : 넋 놓고 비가 오는 날에는 전을 굽자. (2010년 8월 29일 일기)
URL : /901_diary/20100829_rainnyday/
Description : 2022년 8월 29일 경기도 수원시 영통에는 많은 비가 왔습니다. 넋 놓고 비가 오는 날에는 전이 어울립니다.
Content :


구분
내용




날짜
2010년 8월 29일


주제
넋 놓고 비가 오는 날에는 전을 굽자


테그
영통, 비오는 날, 2010년, 8월


장소
경기도 수원시 영통구 영통동


작성일
2022년 10월 어느 날




수원에서 직장생활을 시작한지 2년 정도 된 시기였다.
비가 정말 많이 오던 날이었다.
자취하고 있는 매탄동 원룸에서 전을 구워 먹었다.

당시 삼성전자의 피쳐폰을 사용해서 촬영을 했는데,
사진이 정말 구리가 나왔다.



















["\n \n \n 구분\n 내용\n \n \n \n \n 날짜\n 2010년 8월 29일\n \n \n 주제\n 넋 놓고 비가 오는 날에는 전을 굽자\n \n \n 테그\n 영통, 비오는 날, 2010년, 8월\n \n \n 장소\n 경기도 수원시 영통구 영통동\n \n \n 작성일\n 2022년 10월 어느 날\n \n \n\n\n수원에서 직장생활을 시작한지 2년 정도 된 시기였다. \n비가 정말 많이 오던 날이었다. \n자취하고 있는 매탄동 원룸에서 전을 구워 먹었다.\n\n당시 삼성전자의 피쳐폰을 사용해서 촬영을 했는데, \n사진이 정말 구리가 나왔다.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"]