결론부터 말씀드리면, 텔레그램을 보시고 즉시 매수하고 다음날 아침에 매도 하셨다면 약 10%의 수익률을 볼 수 있었습니다.
<근거>
우리나라 시간으로 2020년 5월 19일 약 11시 42분경, Elon Musk 트위터에 아래의 글이 올라왔었습니다.
저는 텔래그램 알림을 받고 알았는데 "Tesla has" 라고 왔길래 아마도 텍스트만 크롤링 하기에 뒤에 이모티콘이 잘렸나보다 라고 생각하고 컴퓨터로 확인하느라 조금 늦었습니다.
저 그림이 뜻하는 것을 잘 몰라서 구글에 검색해 보았더니 'diamond hands 뜻'이라고 검색해보았더니 아래와 같이 검색되었습니다.
미국 개미들의 아지트는 '월스트리트베츠(Wall street bets·WSB)'라고 불리는 온라인 주식 토론방이다. 특정 종목에 ‘좌표’를 찍고 집중 매수를 권유하는 글, 주식이 떨어질 때 팔지 말라고 당부하는 글이 모두 여기에 올라온다. 주식을 팔지 않고 버틴다는 의미의 ‘다이아몬드핸즈(diamond hands)’나 주가를 달까지 끌어올린다는 의미의 ‘투더문(to the moon)’ 등 수많은 유행어가 이곳에서 나왔다. [출처: 중앙일보] 헤지펀드 박살낸 美 '불개미'…그들 읽는 키워드 ‘SURF’의 뜻
해당 트윗의 뜻을 테슬라가 비트코인을 팔지 않고 '존버'하고 있다라고 해석했고 업비트를 켜서 시세 차트를 확인해보았습니다.
이미 제가 확인 했을 때는 1BTC에 4800만원을 왔다갔다 하고있었지만 해당 트윗이 올라왔을 때는 4600만원이 었던 걸 확인할 수 있습니다. 그리고 다음날 5시 40분 기준 5160만원인 것을 확인했습니다.
즉, 트위터를 보고 즉시 매수를 했다면 하락장에서도 10%정도의 수익을 올릴 수 있었다는 결론을 내릴 수 있습니다.
솔직히 유명인의 말 한 마디 한 마디에 출렁이는 자산과 그걸 유발하는 대중들의 무분별한 투자에 대해서 회의감이 들기도 합니다만, 역으로 이 상항을 잘 이용한다면 수익을 올릴 수 있지 않나 싶습니다. 단, 장기적으로 보았을 때는 유효하지 않을 수 있기에 투자에 유의 바랍니다.
오늘은 최근 코인 열풍의 가장 중심에 있는 테슬라의 CEO인 일론 머스크의 트위터를 실시간 크롤링해보았습니다.
이 프로젝트는 일론 머스크의 말 한마디에 비트코인과 도지코인의 가격이 급등락하는 비이성적인 상황을 이용해서 코인 투자를 해보면 어떨까라는 생각에서 시작하였습니다.
이 프로젝트의 목적은 다음과 같습니다.
"일론 머스크 트위터를 실시간으로 감시하여, 새로운 트윗에 올라 왔을 때 텔레그램 봇을 이용해서 나에게 알려준다"
근 시일 내로 네이버 클라우드 플랫폼을 이용해서, 오늘 만든 코드를 계속 실행시켜줄 나만의 서버를 만들고, 텔래그램 채널을 만들어서 다른 사람들도 이용할 수 있는 서비스로 만들 계획입니다.
<2021년 5월 16일 글 수정>
이 글을 작성한 다음날 우연히 제가 생각하던 서비스를 이미 텔래그램 채널로 구현해놓은 것을 발견하여 공유하고자 합니다.
먼저 텔레그램 앱을 휴대폰에 설치하신 후, 아래와 같이 elon musk twitter 채널을 검색해 줍니다.
위의 채널을 클릭하고 들어가서 화면 화단의 알림켜기를 눌러주시면 실시간으로 일론 머스크 관련 트위터를 받아 보실 수 있습니다.
참고로, Elon Musk 개인 트위터 뿐만 아니라 SpaceX의 트위터도 실시간으로 알려주는 것으로 파악됩니다.
<혼자 진행했던 파이썬 프로젝트 코드>
오늘은 일단 컴퓨터에서 파이썬 코드가 돌아갈 때, 제 개인 텔레그램 봇을 이용해 메시지를 보내는 것 까지 해보았습니다.
전공자가 아니라서 코드가 매우 지저분 할 수 있다는 점 양해바랍니다.
#step1.라이브러리 불러오기
#웹 크롤링을 위한 패키지
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
#사용자에게 메시지 전송을 위한 패키지
import telegram
#주기적으로 프로그램을 작동시키기 위한 패키지
from apscheduler.schedulers.blocking import BlockingScheduler
#step2.텔레그램 봇 불러오기
#토큰을 변수에 저장
bot_token = '자신의 텔레그램 봇 토큰 입력'
#telegram 패키지의 Bot 함수를 사용하여 내가 만든 bot 사용
bot = telegram.Bot(token = bot_token)
#bot과의 채팅 정보 및 메세지 업데이트
#예전(불과 어제)의 정보를 못 불러오는 것으로 파악됨. 프로그램 시작 전에 bot에게 아무 메시지나 보내주어야함
#가장 최근에 온 메세지의 정보 중, chat id만 가져옴 (이 chat id는 사용자(나)의 계정 id임)
chat_id = bot.getUpdates()[-1].message.chat.id
#위에서 얻은 chat id로 bot이 메세지를 보냄.
bot.sendMessage(chat_id = chat_id, text="Elon Musk의 트위터 실시간 크롤링이 시작 되었습니다")
#step3.주기적으로 명령을 실행할 스케쥴러 생성
sched = BlockingScheduler()
#step4.기존에 보냈던 메시지를 담아둘 리스트 만들기
old_contents = []
#step5.트위터 메시지 크롤링 함수 만들기 (매개변수는 이전에 수집해둔 메시지가 담긴 리스트)
def get_content(old_contents=[]):
#크롬드라이버로 일론 머스크 트위터 접속
url = 'https://twitter.com/elonmusk'
driver = webdriver.Chrome('크롬 드라이버의 디렉토리(경로) 입력')
driver.get(url)
time.sleep(3)
contents = []
for i in range(10):
try:
twitter = driver.find_element_by_xpath(f'//*[@id="react-root"]/div/div/div[2]/main/div/div/div/div[1]/div/div[2]/div/div/div[2]/section/div/div/div[{i}]/div/div/article/div/div/div/div[2]/div[2]/div[2]/div[1]/div/span')
contents.append(twitter.text)
except:
pass
time.sleep(3)
new_contents=[]
for content in contents:
if content not in old_contents:
new_contents.append(content)
return new_contents
#step6.텔레그램 메시지 전송 함수 만들기
def send_contents():
global old_contents
new_contents = get_content(old_contents)
if new_contents:
for content in new_contents:
bot.sendMessage(chat_id=chat_id, text=content)
else:
# pass
bot.sendMessage(chat_id=chat_id, text='새로운 트윗 없음')
# else일 때 아무것도 안보내고 싶으면 그냥 pass로 바꾸면 됨. 실제 사용 때는 pass로 할 것
old_contents += new_contents.copy()
# old_contents = list(set(old_contents))
#step7.최초 시작, 스케쥴러 세팅 및 작동
send_contents()
# hours는 시, minutes는 분, seconds는 초
sched.add_job(send_contents, 'interval', seconds=10)
sched.start()
<새로 배운 점>
1. 정적 크롤링 방식으로는 twitter에서 막아둔 것인지 크롤링이 되지 않음 --> 실제 사용자가 클릭하 듯 동적 크롤링 방식 이용
2. css selector로 선택하기 어려운(아직 내가 잘 몰라서) 부분을 xpath의 규칙을 이용해 선택해서 크롤링 함
사용한 코드
for i in range(10):
try:
twitter = driver.find_element_by_xpath(f'//*[@id="react-root"]/div/div/div[2]/main/div/div/div/div[1]/div/div[2]/div/div/div[2]/section/div/div/div[{i}]/div/div/article/div/div/div/div[2]/div[2]/div[2]/div[1]/div/span')
contents.append(twitter.text)
except:
pass
바로 화면의 좌측에 위치하는 위젯(프로그램에서 기능을 하는 버튼 등의 객체)이 그 역할을 합니다.
이곳에서 원하는 위젯을 Dialog Window로 드래그하여 GUI 프로그램이라는 그림을 그려줄 수 있습니다.
Property Editor (속성 편집기)
우리는 도화지와 물감만 있다고 원하는데로 그림을 그릴 수가 없습니다. 의도한 그림을 구현하기 위해서는 붓이 필요하겠죠?
Property Editor는 위젯의 이름(objectName), 위치와 크기(geometry) 등의 특성을 조정해줄 수 있는 창입니다.
Qt Designer로 내 맘대로 GUI 디자인 해보기
위에서 배운 도화지, 물감, 붓 들을 이용해 나만의 그림(GUI)을 그려 보겠습니다. 저는 이것저것 막 드래그해서 아래와 같이 구성해봤습니다.
똑같이 따라하실 필요는 전혀 없습니다! 단순히 버튼 하나만 넣으셔도 됩니다.
이렇게 만들고 저장해주면 생성되는 ui 파일을 코드에서 가져다 사용하면 됩니다. 정말 쉽죠?
어떻게 코드에서 사용하는지 알아보기 전에, 하나만 알고 넘어가시면 좋을 것 같아요.
바로 objectName입니다. 여기서 제가 추가한 QpushButton 위젯 객체의 이름은 pushButton입니다.
나중에 이 버튼 객체를 지난 시간에 배웠던 슬롯(함수)와 연결시켜 어떤 기능을 하기 위해서는 이름을 알고 있어야 합니다.
앞으로 GUI를 디자인 하실 때, 각 위젯의 objectName에 직관적인 이름을 지어주고 사용하시면 됩니다.
참고로 저장 전에 미리보기를 할 수 있습니다. 미리보기 단축키는 Ctrl(Command) + R입니다.
Qt Designer 파일(.UI) 저장
Qt Designer의 UI는 저장 버튼 혹은 단축키(Ctrl + S / Command + S)로 저장을 할 수 있습니다. 저장된 UI파일은 데이터 저장 규칙인 XML 형식을 가지며, Python 코드에서 이 XML 파일을 Import한 후 위젯들에 기능을 할당해주면 실제로 기능을 가지고 작동하는 GUI프로그램이 되는 것입니다.
UI 파일을 저장할 때 주의할 점은 Python코드에서 import하기 쉽도록 Python 코드와 같은 디렉토리에 위치시키는 것이 좋습니다. UI파일의 이름은 원하는 이름으로 아무렇게나 지정해도 됩니다.
UI 파일과 Python 코드의 연결
UI파일과 Python코드를 연결 방법은 2가지로 나뉩니다.
1) UI파일을 Python 코드에서 import하는 방법
2) UI 파일을 코드로 변환해서 Python 코드에 포함시키는 법
코딩유치원에서는 쉬운 방법인 UI파일을 Python 코드에서 import하는 방법에 대해서만 다루도록 하겠습니다.
UI파일과 동일한 위치에 Python파일을 하나 만든 후, 아래의 코드를 그대로 복사/붙여넣기 합니다. 이때 중간에 있는 "UI파일이름.ui"는 자신이 가지고 있는 UI의 이름으로 수정해주셔야 합니다.
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic # ui 파일을 사용하기 위한 모듈 import
#UI파일 연결 코드
UI_class = uic.loadUiType("UI파일이름.ui")[0]
class MyWindow(QMainWindow, UI_class) :
def __init__(self) :
super().__init__()
self.setupUi(self)
app = QApplication(sys.argv)
Window = MyWindow()
Window.show()
app.exec_()
위의 코드를 실행시켰다면 성공적으로 Qt Designer를 이용하여 제작한 GUI가 표시되는 것을 볼 수 있습니다.
다음 시간에는 지금까지 배워왔던 것을 갖고 간단한 기능을 하는 GUI 프로그램을 만들어보겠습니다.
오늘은 주말에 읽은 에리히 프롬이 1941년에 출판한 '자유로부터의 도피'에 대한 독후감을 써보려 한다.
이 책은 사회심리학 분야의 고전으로 예전에 한 번 펼쳤다가 생각보다 높은 난이도에 접어두었던 책이었다.
적지 않은 책을 읽어왔지만 손꼽히게 힘들었다.. 약간만 집중을 안해도 문장이 이해 안가는 그런 느낌이랄까.
자유로부터의 도피는 중세 사회의 붕괴와 그로 인해 얻게 된 자유가 가져온 인간의 불안이라는 현상을 분석한 책이다.
이 책의 내용을 최대한 쉽게 요약하면 다음과 같다.
중세시대에는 아주 특수한 경우를 제외하고는 태어난 곳을 떠나지 못하고, 농민, 장인, 기사 등의 역할이 태어나면서 정해져서 바꿀 수 없었다.
모든 것이 태어나면서 정해진 사회, 이러한 사회 체제는 자연적 질서로 여겨졌고, 그 체제의 확실한 일부가 되는 것은 안전감과 소속감을 주었다.
근대인은 여러 혁명들을 통해 중세시대의 신분제, 종교의 굴레에서 벗어나 경험해보지 못한 자유를 얻게 되었다.
자유는 근대인에게 독립성과 노력을 통해 삶을 바꿀 수 있는 가능성을 가져다주었다.
하지만 한편으로는 완전히 독립된 존재로서 외부의 거대한 세계와 마주하게 되면서 개인을 무력하고 고립된 존재로 만들었다.
인간에게는 식욕, 갈증, 수면욕과 같이 충족시키지 않으면 생존이 불가능한 생리적 욕구만큼 중요한 욕구가 있다.
이 욕구는 인간을 사회적 동물이라고 부르게 하는 이유이며, 그것은 바로 '외부 세계와 관계를 맺고자 하는 욕구, 즉 고독을 피하려는 욕구다.
혼자 고립되어 있다는 느낌은 정신적 분열을 초래할 정도로 소속감은 매우 중요하다.
갑자기 주어진 자유의 무게가 버거운 개인들은 스스로 기계의 작은 톱니가 되어 자유로운 인간이 아닌 자동인형이 되고 싶은 유혹에 사로잡힌다. 그래서 수 많은 개인들은 어딘가에 종속되어 자발적으로 권위에 복종하며, 안전감과 소속감을 얻는 방식을 선택해왔다. 이 책에서는 여러가지 예들 중 한가지로 독일의 '파시즘'을 예로 든다.
책에서는 '적극적인 자유'를 얻기 위한 방법으로 다음과 같은 방법을 제시한다.
- 사랑과 일 모두에서 능동적이고 자발적으로 살며, 자신의 감정적, 감각적, 지적 능력을 진정으로 표현하는 것
- 개인의 가치관을 외부 요구에 의한 것이 아닌 자신의 판단으로 세우는 것, 그것을 추구하며 자아실현 하는 것
- 성공만 바라보고 현재를 희생하는 것이 아닌, 지금 이 순간을 생생하게 경험하고 느끼며 소중히 여기는 것
이를 통해 바깥 세계와 자연스럽게 관계를 맺을 수 있으며, 그리하여 자신의 개체적 자아의 독립성과 본래의 모습을 포기하지 않고도 인간과 자연 및 그 자신과 다시 일체가 될 수 있다고 말한다.
여기까지가 책의 내용이고, 나의 생각을 써보고자 한다.
개인들은 시대가 바뀌어도 여러 방식과 모습으로, 자신의 자유를 어디엔가 반납하고 안정감을 취해왔고 현재는 직장인이라는 형태로 존재한다고 생각이 들었다. 물론 회사를 다닌다는 것 자체가 나쁘다고는 생각하지 않는다. 큰 일을 하기 위해서는 혼자서는 한계가 있으며, 가장 효율적인 조직인 기업에서 시스템을 체험하고 배우는 것은 도움이 된다. 또한 당장의 생계를 해결한다는 점에서도 의미가 있다.
하지만 지금 내가 하는 일이 의미 없다고 느껴지고, 시간을 팔아서 돈을 받고 있다는 느낌이 든다면.. 그럼에도 현재의 월급과 안정감, 소속감을 버릴 수 없거나 내 능력에 자신이 없어서 회사에 꼭 붙어있어야겠다는 생각이 든다면 그것이 바로 이 책에서 언급한 자유를 포기하는 행위가 아닌가 싶다.
자유는 개인에게, 아니 나에게 여전히 무거운 존재라고 생각한다. 과거 학창시절 방학에 학교를 가지 않을 때는 넘쳐나는 시간을 어찌할 바를 몰라 허투루 쓴적이 많고, 현재도 주말에 많은 시간을 밀도있게 쓰지 못하는 나 자신을 발견하곤 한다. 또한 개인의 능력과 노력에 따라 엄청난 빈부의 차이를 만드는 자본주의 시대에서 내 능력에 대한 끝없는 의심은 나를 불안하게 만든다.
솔직히 나는 아직 '적극적인 자유'를 얻지 못하고 있다. 여전히 직장인으로 회사의 보호와 안정적인 월급을 받으며, 평균에 비해 좋은 환경에서 일한다는 위안을 얻고 있다. 여전히 사회가 보편적으로 원하는 성공의 모습을 추구하며, 현재를 있는 그대로 즐기지 못하고 미래를 걱정하며 살아가는 중이다.
이 책을 읽는다고 당장 내 삶이 드라마틱하게 바뀌지는 않을 것을 잘 안다. 하지만 이 책을 통해, 나를 비롯한 현대인들이 느끼는 불안감이 어디에서 비롯된 것인지 알 수 있었고, 어떻게 해야 불안감을 해결할 수 있는지 어렴풋이 알게 되었다. 여기에 적을 수는 없지만 내가 생각한 방법들을 오늘부터 내 삶에 적용해보고자 한다.
물론 내가 결론 내린 그 방법들이 먼 훗날 되돌아봤을 때 정답이 아닐수도 있다.
그러면 어떠한가? 지금의 내가 선택했고 옳다고 생각하는 것. 그것을 용기있게 실행하는 것이 적극적인 자유고 진정한 행복이 아닐까 싶다.
이 코드는 btn이란 이름의 QPushButton의 인스턴스가 클릭되었을 때, ( )안의 메소드(슬롯)와 연결해주는 역할을 하죠.
슬롯은 def surprise(self): 로 정의하였습니다. 이 슬롯은 위에서의 .connect( )로 시그널과 연결되는 것입니다.
이벤트 루프
혹시 지난 시간에 배웠던 코드 중에 닫기 버튼 누를 때 까지 계속 GUI 프로그램을 실행시키는 코드를 기억하시나요?
app.exec_( ) 를 프로그램의 마지막에 입력하시면 루프를 돌며, '닫기' 이벤트가 발생하기 전까지 GUI 창을 계속 띄워놓는 코드입니다.
그래서 이벤트 루프라고 부르며, 이벤트라는 것은 사용자가 마우스클 클릭하거나 키보드를 입력하는 것과 같은 동작을 의미합니다.
참고로, exec_( ) 앞에 붙는 app은 QApplication 클래스의 인스턴스이며, 이름은 app 말고도 원하는대로 지어주시면 됩니다.
exec_( ) 메서드를 호출하면 이벤트 루프가 생성되고 실행됩니다. 이를 보다 명확히 알아보기 위해 다음과 같이 print( ) 함수를 추가해서 커맨드 창을 관찰해보시면 좋을 것 같습니다.
import sys
from PyQt5.QtWidgets import *
class MyWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
btn = QPushButton("버튼", self)
btn.clicked.connect(self.surprise)
def surprise(self):
print("으엌! 깜짝이야!!")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MyWindow()
window.show()
app.exec_()
#해당 코드 실행 시 부터 이벤트 루프 발생 (즉, 이 코드 아래로는 이벤트 발생 전까지 안내려감)
app.exec_()
print("루프 밖")
이번 시간에는 위젯의 종류와 입력/시그널/슬롯 간의 관계에 대해서 알아보았습니다.
다음 시간에는 Qt Designer를 이용해 위젯을 실제로 구성해보고, 슬롯을 정의해서 연결시켜보면서 실제 프로그램을 만들기 위한 공부를 해보겠습니다.
이를 이용해 window라는 이름으로 객체를 생성한 후에 show 메소드로 창을 띄워줍니다.
여기서 Qwidget( )는 그냥 창의 껍데기만 만드는 것이라고만 이해하고 넘어가도록 합시다.
4) 닫기 버튼 누를 때 까지 계속 실행하는 코드
app.exec_()
위의 소제목과 같이 닫기 버튼을 누를 때 까지, 루프를 돌며 GUI 창을 계속 띄워놓는 코드입니다.이 부분은 다음 강의에서 자세히 설명드릴테니, 이정도로 이해하고 넘어가겠습니다.
3. 나만의 윈도우 만들기
아래와 같이 아이콘과 창 이름을 넣어주고, 원하는 위치에 원하는 크기로 창을 띄우는 실습을 통해서 PyQt에 대해서 알아보도록 하겠습니다.
1) 윈도우 생성
PyQt에서 모든 위젯의 가장 기초가 되는 위젯을 윈도우라고 부릅니다. GUI를 만드는 것을 그림 그리는 것이라 생각하면 윈도우를 생성하는 것은 도화지를 준비하는 것입니다.
<도화지 코드>
import sys
from PyQt5.QtWidgets import *
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
app = QApplication(sys.argv)
window = MyWindow()
# 위의 기본 코드와 다른 점
# QMainWindow 클래스를 상속받은 MyWindow 클래스를 선언
# 그 후 부모클래스를 의미하는 super()메소드와 그 클래스의 속성을 불러오는 __init__ 초기화 메소드 사용
# QMainWindow의 속성이 무엇인지는 모르겠음
window.show()
app.exec_()
아까 처음 본 코드와의 차이점은 class MyWindow 부분과 window = MyWindow( ) 부분 입니다.
나만의 윈도우 클래스를 만들어서 사용하기 위해 PyQt가 제공하는 QMainWindow를 상속 받아서 MyWindow라는 클래스를 정의해주어야 합니다.
한마디로 MyWindow라는 클래스의 역할은 객체를 생성했을 때, 부모 클래스인 QMainWindow의 def __init__의 속성과 메소드를 불러오거나 실행시켜주는 역할이라고 생각하면 됩니다.
2) 윈도우 타이틀 변경
원하는 창의 이름을 넣어 주고 싶을 땐 아래와 같이 setWindowTitle( ) 메소드를 사용합니다.
def __init__(self) 메소드 안에 self.setWindowTitle("원하는 창 이름")을 넣으주면 됩니다.
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
# 도화지 코드의 이 위치에 아래 코드 한 줄을 추가할 것
self.setWindowTitle("코딩유치원 GUI")
3) 윈도우 크기 변경
QMainWindow 클래스에는 윈도우의 출력 위치 및 크기를 변경하는 메서드인 setGeometry( )가 정의되어 있습니다.
아래의 코드는 setGeometry( ) 메서드를 사용해서 창의 좌측상단 꼭지점의 좌표가 300, 300이며 창의 크기가 400x400이 되도록 윈도우를 셋팅하는 코드입니다.
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
# 도화지 코드의 이 위치에 아래 코드 한 줄을 추가할 것
self.setGeometry(300, 300, 400, 400) # 차례대로 창위치 x,y, 창크기 x,y
4) 윈도우에 예쁜 아이콘 넣기
구글에서 icon-icons 사이트를 검색하거나 아래의 링크에서 아이콘 이미지 다운로드합니다. 테스트 해보니, 이미지 사이즈는 상관 없습니다.
QIcon 클래스의 인스턴스를 생성할 때는 인자로 아이콘 파일의 경로를 문자열로 넘겨주면 됩니다.
현재 예에서는 소스코드와 아이콘 파일이 같은 디렉터리에 있기 때문에 파일 이름만 적어주면 됩니다.
# 아이콘 삽입 클래스(QIcon) 사용을 위한 PyQt5 패키지의 QtGui 모듈 import
from PyQt5.QtGui import *
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
# 해당 위치에 아래 코드 추가
self.setWindowIcon(QIcon("pie-chart.png"))
깃(git)은 프로그램의 개발 시, 소스 코드의 버전을 체계적으로 관리하기 위해 만들어진 분산 버전 관리 시스템입니다.
저는 제조 회사를 다니고 있는데, 관리는 이력 관리가 기본이라는 것을 많이 느꼈습니다. 인간의 기억력은 한계가 있으니까요!
그런 관점에서 코드의 수정이 더욱 빈번하게 일어나는 프로그램 개발자 사이에서 Git은 매우 유용하고 필수적인 도구가 아닌가 싶습니다.
깃은 네트워크를 통한 중앙 서버에 소스 코드를 저장하는 것이 아니라, 자신의 컴퓨터에 로컬 저장소를 만들어 저장하는 것이 특징입니다.
로컬 저장소에 저장하는 것의 장점은 인터넷이 없는 환경에서도 마음껏 코딩하고, 깃을 이용해 이력 관리를 한 후, 인터넷이 연결된 환경에서 깃허브(GitHUb)와 같은 웹 호스팅 서비스에 등록하여 사람들과 협업할 수 있습니다.
깃 만큼 많이 쓰이는 버전 관리 시스템에는 SVN(Subversion)이라는 것이 있습니다. SVN은 중앙 집중식 소스코드 관리이지만, 깃은 분산 소스코드 관리 방식을 사용합니다. 그렇기 때문에 중앙의 저장소에 문제가 생기면 SVN은 큰 문제가 되겠지만 깃은 분산된 로컬 저장소를 활용한 중앙 저장소 복구가 가능하다는 장점이 있습니다.
앞서 언급한 인터넷 환경에 구애받지 않는 점, 유사시 중앙 저장소 복구가 가능하다는 점으로 인해 최근에는 SVN을 사용하던 많은 기업들도 깃(Git)으로 많이 전환하고 있는 추세입니다.
깃허브(GitHub)란?
앞서 설명드린 깃(Git)으로 관리하는 프로젝트를 호스팅해주는 웹 서비스이며, 깃 저장소 서버를 대신 유지 및 관리해주는 서비스입니다.
다른 유저들과 함께 온라인으로 하나의 프로그램을 제작하는 것도 가능하여, 많은 오픈소스 프로그램들이 github을 통해서 전세계 유저들에 의해 제작되고 있습니다. 참고로 오픈소스 프로젝트는 무료이며, private 프로젝트는 유료입니다.
깃허브에 저장하는 것은 매번, 매버전을 모두 저장하고 업로드하는 방식이 아닌 각 버전들의 차이 혹은 변경이력을 저장하는 것입니다.
이를 통해서 훨씬 적은 용량으로 많은 버전 이력들을 저장할 수 있는 것입니다.
GitHub 사용을 위한 기본지식
깃허브 개념도
저장소(repository)
저장소(repository)는 파일이나 디렉토리를 저장하는 장소입니다. 기본적으로 PC에 존재하는 로컬 저장소에서 작업을 진행하고 그 결과를 GitHub의 원격 저장소에 저장할 수 있습니다.
1. 메인 저장소(Main repository)
메인 저장소는 오픈소스 프로젝트의 github상의 메인 repository를 의미하며 upstream이라고도 부릅니다. 이 저장소는 세계적인 프로그래머가 만든 큰 프로젝트의 저장소이므로 나에게는 쓰기 권한이 없습니다. 실력이 된다면 메인 저장소의 주인에게 나의 변경사항을 반영해달라고 요청할 수 있습니다. 만약 채택된다면 거대한 프로젝트의 컨트리뷰터(Contributor)가 되는 명예를 얻게 된다고 하네요.
2. 원격 저장소(remote repository)
내 로컬 저장소의 버전을 업로드하거나 메인 저장소의
github상에서 나의 계정상에 존재하는 전용 repository로 메인 저장소로 부터 fork(코드를 가져오는 것)한 저장소입니다. 일반적으로 이를 origin이라고 부릅니다.
3. 로컬 저장소(Local git repository)
검퓨터에 생성한 로컬 저장소를 말합니다. 깃 저장소를 만들게 되면 해당 디렉토리에 .git/ 폴더가 생성됩니다.
흔히 개발자들이 말하는 '1일 1 커밋'의 커밋은 작업 공간에서 로컬 저장소로 업로드하며, 기록을 남기는 것을 말합니다.
4. 작업 공간(workspace)
내 컴퓨터 상에서 실제 내가 소스를 개발하고 수정하는 workspace를 의미합니다. 쉽게 말해서 우리가 코딩을 위해 만든 폴더라고 생각하시면 됩니다.
브랜치(branch)
소프트웨어는 출시된 이후에도 지속적인 유지 보수를 통해 기능을 추가하거나 버그를 수정하게 됩니다. 브랜치란 독립적으로 개발이나 유지/보수 작업을 진행하기 위한 개념입니다. 필요에 의해 만들어지는 각각의 브랜치는 다른 브랜치의 영향을 받지 않기 때문에, 여러 작업을 동시에 진행할 수 있으며, 추후에 병합(merge)하여 새로운 하나의 브랜치로 모을 수 있습니다.
자세한 내용은 아래 링크를 참고하시면 좋겠습니다. 글 쓰는 마지막에 발견한 곳인데 깃과 깃허브에 대해서 너무 잘 정리되어있네요!
파일을 추가하거나 변경사항을 저장소에 기록하기 위해 커밋 메시지를 남기는 작업을 말합니다.변경한 사람, 시간, 변경 내용 등을 기록해 과거 변경 이력과 내용을 손쉽게 파악할 수 있습니다. 좋은 커밋 메시지를 작성하는 Tip을 정리한 글을 아래에 링크해놓았으니 참고해주세요.
클론을 사용하면 원격 저장소의 코드를 내 컴퓨터에 받아올 수 있고 로컬 저장소(.git)도 자동으로 생기게 됩니다. 이어서 설명할 Pull과 Clone은 비슷하지만 다른 점이 있습니다. Clone은 로컬에 아무것도 없는 상태에서 원격저장소의 데이터를 가져오는 것을 의미하지만, Pull은 로컬에 이미 코드가 있고, 원격저장소의 수정 상태를 반영하기 위해 하는 것 입니다.
풀(Pull)
원격 저장소 변경 사항을 받아오는 것을 말합니다.공동작업의 경우,다른 사람이 원격 저장소에 업데이트한 파일이 있을 때 원격저장소와 내 로컬저장소의 상태를 동일하게 만들기 위해 pull을 이용합니다. Clone과 Pull 모두 원격저장소에서 로컬저장소로 가져오는 것이므로 헷갈리기 쉬우니 차이를 잘 이해하시고 넘어가시면 좋겠습니다.
푸쉬(push)
로컬 저장소에 저장되어 있던 커밋을 원격 저장소(GitHub)로 업로드하는 것을 말합니다.
속성으로는 계좌번호와 계좌잔액을 가지며, 메소드로는 계좌잔액을 모두 인출하는 withdraw_all 메소드를 가지는 클래스입니다.
여기서 self라는 생소한 개념이 보입니다. 클래스를 사용하려면 이 self에 대한 이해가 필수적입니다.
self란?
메소드 선언 시 사용된 self는 객체가 자기 자신을 참조하는데 사용하는 매개변수입니다.
self를 사용하면, 메소드에서 클래스에 정의된 모든 속성 및 다른 메소드에 접근할 수 있습니다.
파이썬에서는 메소드를 선언할 때 첫 번째 매개변수로 반드시 self를 명시하도록 하고 있으며, 메소드를 호출할 때는 self 매개변수에 아무런 인수를 전달하지 않아도 됩니다.
4) 인스턴스 생성
인스턴스란 클래스를 기반으로 생성된 객체를 가리킵니다. 그냥 객체라고 해도 되겠지만 특별히 어떤 클래스의 객체라는 것을 말해주는 느낌이랄까요. 마치 영희(객체)라는 사람이 있는데, 굳이 미영이의 딸(OO 클래스의 인스턴스)이라고 부르는 느낌이라고 생각하시면 되겠습니다. 완벽한 예는 아닌듯하지만 느낌만 가져가시면 좋겠습니다.