전체 글
-
2022년도 1월 - 연구실 인턴 합격 회고2022.01.22
-
[입문자 튜토리얼] - C언어 소스 코드 파일 분리 2편 (feat. 헤더파일)2021.12.19
-
[Github] 깃허브 왕초보 사용법 - 기본편32021.12.19
-
[Github] 깃허브 왕초보 사용법 - 기본편22021.12.19
2022년도 1월 - 연구실 인턴 합격 회고
바빴던 계절학기와 찾아온 연구실 인턴 기회
근황 요약: 빡빡한 계절학기를 마치고, 뜻밖의 연구실 인턴 기회를 얻었다.
1. 숨 가빴던 계절학기
지난 3주 동안 6학점(자료구조, 대학미적분학)의 계절학기를 들으며 정신없이 보냈다. 비대면 수업이었지만, 매일 6시간 상당의 강의를 듣고 필기하며 따라가는 것도 벅찼다. 특히 수학에 약한 저에게 미적분학은 큰 산이었다.
계절학기 시작 전 자료구조 스터디를 했던 덕분에 그나마 자료구조 수업은 수월했지만, 새로운 내용도 많아 꾸준히 공부해야 했다. 설상가상으로 외할아버지 장례식까지 겹쳐 더욱 시간적 여유가 없었다. 어제 드디어 기말고사를 마무리했다.
2. 꾸준한 프로그래밍
계절학기 중 자료구조 수업에서 구현했던 프로그램들을 깃허브에 정리하고 블로그에도 공유할 생각이다. 현재는 계절학기 마지막 과제를 진행 중이다. 한편, 개인적으로 진행했던 IPC 통신 프로젝트 'minitalk' (42서울 프로젝트)의 동료 평가까지 완료했다. 제시된 구현 사항은 모두 통과했지만, 비동기 시그널의 interrupt 이슈를 해결하지 못한 점이 아쉽다. signal block 등을 공부하며 해결책을 모색했지만, 데이터 손실 문제로 인해 아직 명확한 해결 방법을 찾지 못했다. 언젠가 이 부분을 해결하고 싶다.
미래에는 클라이언트 수를 확장하고 GUI까지 갖춘 IPC 통신 프로그램을 개발하여 누구도 뚫을 수 없는 보안성이 뛰어난 프로그램을 만들고 싶다. 더 나아가 가상 머신 환경에서 인터넷 연결 없이 IPC 통신만으로 작동하는 프로그램도 구상 중이다. 인터넷 통신 외에도, 제한적인 환경에서의 프로그램 간 통신의 중요성을 느낀다.
3. 예상치 못한 연구실 인턴 기회
졸업 전 인턴 경험을 쌓고 싶었는데, 학부연구생(연구실 인턴)에 관심을 가지던 중 지인을 통해 타 대학 연구실 인턴 공고를 보게 되었다.
같이 42서울이나 스터디하던 친구들도 다 새로운 길을 찾아 인턴 등을 시도하는데,
내가 재학 중인 학교는 항공 연구에 주로 집중되어 있는 편이라 내게는 마땅히 지원할만한 자리가 없었던 상황이었다.
연구실 주제가 평소 관심 있던 분야(네트워크/알고리즘)였고, 프로젝트들도 흥미로웠다.
하지만 그곳은 소위 '넘사벽'이라 불리는 SPK 연구실 중 하나였기에 솔직히 많이 망설였다.
주변 친구도 걱정했지만, 배우는 것이 있을 거라 생각하고 용기를 내어 CV를 제출했다. 블로그, 깃허브, 노션에 정리해두었던 학습 내용들이 CV를 통해 저를 보여주는 데 큰 도움이 되었다. 아주 놀랍게도 줌 면담 제의가 왔고, 면담은 예상과 달리 매우 편안한 분위기 속에서 진행되었다. 교수님은 정말 온화하셨고, 박사 과정생분들은 제 깃허브 활동에 관심을 가져주셨다. 면담 후 몇 시간 뒤, 바로 출근 가능 여부를 묻는 연락을 받았다!
비대면 학기제 덕분에 타 대학 연구실 인턴십과 학교 수업을 병행할 수 있다는 점을 어필했던 것이 긍정적으로 작용한 것 같다. (최근 학교 확진자 증가 추이를 보면 이번 학기도 비대면일 가능성이 높아 보인다.)
사람의 인생에서 찾아오는 기회에는 대부분 시기가 있다고 생각한다.
지금이 제가 배우고 싶은 분야에서 경험을 쌓을 절호의 기회라고 생각한다. 학부 인턴의 급여는 크게 중요하지 않다. 오히려 지금도 수도권에서 자취하고 있어서, 거기 가도 생활하는 건 비슷하고 오히려 생활비가 조금 절약될 수도 있다.
게다가 월급이 다가 아니지 않은가? 돈 주고도 배우기 힘든 기술들을 그곳에서 열심히 일하면서 배울 수 있다면 내게는 정말 좋은 기회이다. 심지어 무급 인턴이라고 해도 갈 생각이다.
인생에서 돈보다 더 소중한 건 경험이라고 생각한다. 본인의 가치를 성장시킬 수 있는 경험이 얼마나 중요한지 깨달은 이후라 더욱 그렇다. 몇 년 전에 용돈 벌이 겸해서 편의점 아르바이트를 5개월 정도 했었다. 계속 일하고 싶었지만, 코로나 때문에 가게 매출이 줄어서 점장님이 근무 시간을 조정해야 하는 상황이 왔었다. 그래서 심야 아르바이트로 바꿔달라는 요청을 받았는데, 제가 학생이다 보니 밤새 일하는 건 좀 힘들어서 결국 그만두게 되었다. 단순 노동 아르바이트는 끝나고 나면 크게 남는 게 없다.
경험은 되었지만, 대개 초보적인 단순 노동은 많이 한다고 해서 제 가치가 크게 올라가지는 않는다. (이래서 어른들이 공부하라고 하셨구나 싶었다.) 그 이후부터는 쭉 뭔가를 배우면서 성과를 낼 수 있는 일을 해보고 싶었다.
4. 나를 만든 환경
돌이켜보면 나는 주변 환경에 큰 영향을 받는 사람이었다.
1학년 때 목표 없이 대학에 진학하고 우울증으로 힘든 시간을 보냈다. 프로그래밍은 낯설고 어려워 혐오하기까지 했다. 하지만 2학년 때 코로나로 비대면 수업이 진행되면서, 그리고 좋은 친구들을 만나 함께 공부하면서 점차 변화하기 시작했다. 차석 친구를 따라 공부하며 학점도 올랐고, 친구의 권유로 참여한 42서울 활동을 통해 코딩에 대한 흥미를 느끼고 적극적으로 배우려는 태도를 갖게 되었다. 동료 평가를 통해 배운 내용을 정리하는 습관이 생겼고, 제 코드를 설명하고 개선하는 것에 대해 고민하게 되었다.
대외활동을 통해 세상은 넓고 열정적인 사람들이 많다는 것을 깨달았고, 더이상 멈춰있고 싶지 않다는 욕심이 생겼다.
기본기가 다져지니 프로그래밍이 즐거워졌고, 더 완벽한 프로그램을 만들고 싶어졌다.
친구들과 매일 학습 내용을 인증하는 단체톡방 챌린지를 통해 꾸준히 노력하는 습관도 갖게 되었다.
나를 변화시켜준 친구와 내 주변인들에게 정말 감사하다.
친구가 나한테 같이 대외활동을 하자고 하지 않았다면,
날 프로그래밍 학원과 각종 공부챌린지, 스터디 등에 껴주지 않았더라면...?
아마 난 지금도 그 자리였을 것이다.
솔직히 1학년의 나를 보면 그냥..모든게 다 엉망이었는데 나같은 애를 어떻게 이끌어줄 생각을 했는 지.
그 친구가 너무 대단하고 존경스럽다.
내가 성공하면 주변인들 덕이고, 내가 실패하면 내 탓이다.
난 정말 주변으로부터 많은 도움을 받고 살아가는 것 같다. 모든 걸 감사히 생각하고 오늘도 열심히 살아야겠다.
'Experience > 주제별' 카테고리의 다른 글
인프라를 지망하게 된 계기 (Kubernetes & Golang 관련 계획) + 뻘글 (0) | 2025.06.09 |
---|---|
Azure AI Developer 해커톤 (수상내역) / 회고록 (0) | 2025.05.02 |
[자기계발] 게으름을 고쳐보자! 만원챌린지 (0) | 2021.11.08 |
42서울 : 라피신 후기 + 본과정 합격 후기 (4기 2차 : 3 /22 ~ 4/16) (0) | 2021.05.20 |
[번역] C에서 시그널을 보내고 처리하는 방법 (kill, signal, sigaction)
Sending and Handling Signals in C (kill, signal, sigaction)
- 참고하면 좋은 자료 (만화) : sigterm vs sigkill 차이점
- What is SIGTERM? What's the difference between SIGKILL & SIGTERM?
해당 영상의 내용을 정리한 자료입니다. 문제 시 댓글 주시면 삭제하겠습니다.
최근 42 과제 미니톡을 진행하며, 시그널 프로그래밍에 관심이 생겨 이것저것 유튜브로 강의와 영상을 찾아보고 있었습니다. 그 중에 흥미롭고 짧은 영상이 있어 내용을 정리하여 공유합니다.
시그널이란?
시그널은 당신이 프로세스와 상호작용할 수 있는 가장 간단한 방법 중 하나입니다.
mac이나 리눅스와 같은 모든 unix 스타일 운영체제에서 말이에요.
혹시 리눅스나 맥같은 unix 운영체제를 쓰고있으신가요? 그동안 몰랐겠지만, 당신이 프로그램을 종료시키기 위해 ctrl + C를 누를 때마다 시그널들을 사용하고 있던 겁니다.
시그널 처리 (시그널 핸들러)
그럼 이제 예시를 하나 살펴보도록 할까요.
절대 종료되지 않는 무한루프 프로그램이 있다고 해봅시다. 그냥 영원히 실행되고 있는거에요.
보통 학생들의 경우에 이런 코드는 실수로 작성된 것이겠지만, 이건 설명하려는 목적이니까 일부러 이렇게 만들어봤습니다.
#include <stdlib.h>
#include <unistd.h>
int main()
{
while (1)
{
printf("Wasting your cycles. %d\\n", getpid());
sleep(1);
}
}
이런 경우 아래와 같은 실행 화면이 무한히 나타나게 되는데요. 그러면 당신은 이 화면을 잠시 보다가, 프로세스를 죽이기 위해서 주로 ctrl+C를 누르게 될거에요.
이때 당신은 알지 못했겠지만 프로세스에 SIGINT 시그널을 보낸 것입니다. 이 시그널은 기본적으로 해당 프로세스를 방해하고 그 프로세스를 끝내라고 전해주는 역할을 해요.
아직까진 별로 재미없네요. 그럼 내용을 조금 바꿔서 더 재밌게 해볼까요.
이제는 ctrl + C를 눌렀을 때 다른 일들이 일어나도록 만들어볼거에요.
일단 특정한 시그널을 받았을 때 언제든지 호출되는 그런 함수를 만들어 볼 수가 있어요. 그리고 시그널 함수를 이용해서 그 함수를 등록할 수 있습니다.
그래서 여기서는 SIGINT 시그널을 받았을 때 handler 함수가 실행되도록 했습니다.
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void handler(int num)
{
write(STDOUT_FILENO, "I won't die\\n", 13);
}
int main()
{
signal(SIGINT, handler);
while (1)
{
printf("Wasting your cycles. %d\\n", getpid());
sleep(1);
}
}
그럼 이걸 실행시켜 보는 중에 ctrl + C를 누르면 이렇게 나옵니다.
그동안 봐온 것 중 가장 건방진 C 프로그램이 만들어지죠.
프로그램이 절대 죽지 않는다는 데, 그럼 이때는 어떻게 할 수 있나요.
운 좋게도 제가 보낼 수 있는 다른 시그널들이 있네요. 이 프로그램이 자기 process ID를 출력하도록 만든거 기억나시나요? 이 다음 파트를 좀 더 쉽게 하기 위해 만들었던 거였어요.
그럼 이제 SIGTERM이라는 시그널을 보내는 걸 해봅시다.
SIGTERM은 해당 프로세스로 가서 그 프로세스 스스로를 종료시키라고 강하게 명령합니다.
그런데 제가 아직 SIGINT 이외의 시그널들을 보내는 법은 설명하지 않았죠. 바로 kill 명령어를 사용하면 시그널을 보낼 수 있어요.
좀 폭력적인 느낌이 들기도하는 별로인 이름이죠. 그렇지만 꼭 저 말 뜻 그대로 되는 하는 것은 아니에요. 네 가끔은 프로세스들을 죽이기도 하지만 가끔은 그렇지 않다네요...
간단히 말하면, 그냥 메시지를 보내는 거에요.
프로그램 내부에서(코드 중에서) kill()을 호출할 수도 있지만 이런 식으로 명령어로도 실행할 수 있답니다.
$ kill -TERM 28272
내가 보내고 싶은 시그널과 프로세스 ID를 같이 입력해주면?
와 이걸 보세요. 프로세스를 죽이는 데 성공했습니다.
그렇지만 SIGTERM도 같이 처리하려는 제 건방진 자아는 아무도 막을 수 없죠. 이렇게 signal 함수를 통해 SIGTERM에 대한 핸들러를 추가해줍니다.
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void handler(int num)
{
write(STDOUT_FILENO, "I won't die\\n", 13);
}
int main()
{
signal(SIGINT, handler);
signal(SIGTERM, handler);
while (1)
{
printf("Wasting your cycles. %d\\n", getpid());
sleep(1);
}
}
그럼 이렇게 나오네요.
$ kill -TERM 28297
kill -TERM 명령어를 입력해봤자 아직 너무 잘 살아있는 상태에요. 그렇지만 운 좋게도 우리에겐 아직 sigkill이라는 방법이 남았습니다. 아마 가끔씩 사람들이 kil -9 이런 이야기를 하는 걸 들어본 적 있을 거에요. 그거랑 같은 방법입니다. 한번 해봅시다!
하하 이제 저 프로세스에게 따끔한 맛을 보여줍시다. 하하 정의의 무게가 느껴지시나요 여러분.
$ kill -KILL 28297
그럼 계속해서 SIGKILL도 핸들러가 관리하도록 해볼까요.
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void handler(int num)
{
write(STDOUT_FILENO, "I won't die\\n", 13);
}
int main()
{
signal(SIGINT, handler);
signal(SIGTERM, handler);
signal(SIGKILL, handler);
while (1)
{
printf("Wasting your cycles. %d\\n", getpid());
sleep(1);
}
}
그렇지만 운 좋게도, 그건 먹히지 않을거에요. SIGKILL은 저런 방식으로 처리할 수 없습니다. SIGKILL은 간단히 말해 요청(request)가 아닌 명령(order)이기 때문이에요.
외부 명령어 창에서 KILL -9 28450을 입력해주니 프로세스가 kill 된 것을 볼 수 있습니다.
$ kill -9 28450
시그널의 다양한 역할
시그널은 단지 프로세스를 죽이는(kill) 것 뿐만 아니라, 더 많은 일들을 할 수 있습니다.
예를 들자면, 프로세스를 멈출 수 있고요 (stop).
$ kill -STOP 28486
멈췄던 프로세스를 계속 이어지도록 할 수도 있습니다. (continue)
$ kill -CONT 28486
또, 통신을 목적으로 사용자 정의 시그널 (SIGUSER1, SIGUSER2)를 사용할 수도 있습니다. 그것들은 당신이 정의하고자 하는 대로 정의됩니다.
그리고 정말 특이하게도, 프로그램은 segfault가 되었을 때조차 시그널을 받습니다. 진짜에요.
그럼 이걸 빨리 확인 해보도록 할까요.
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void handler(int num)
{
write(STDOUT_FILENO, "I won't die\\n", 13);
}
int main()
{
int *p = NULL;
signal(SIGINT, handler);
signal(SIGTERM, handler);
signal(SIGKILL, handler);
*p = 45 // segfault를 일으킨다
while (1)
{
printf("Wasting your cycles. %d\\n", getpid());
sleep(1);
}
}
위 코드를 실행하면 세그폴트를 일으킬 거에요. 그리고 실제로 확인해봐도 그렇네요.
이때 시그널에서 Segfault를 처리해주었지만 상황을 해결하지는 못했습니다. 잘못된 포인터 문제를 해결하지 못했어요. 시그널을 처리해줘도 잘못된 메모리 접근을 계속할 뿐입니다.
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void handler(int num)
{
write(STDOUT_FILENO, "I won't die\\n", 13);
}
void seghandler(int num)
{
write(STDOUT_FILENO, "Seg Fault!\\n", 10);
}
int main()
{
int *p = NULL;
signal(SIGINT, handler);
signal(SIGTERM, handler);
signal(SIGKILL, handler);
*p = 45 // segfault를 일으킨다
while (1)
{
printf("Wasting your cycles. %d\\n", getpid());
sleep(1);
}
}
$ killall a.out
결국 해당 명령어를 통해 프로세스를 종료해주었습니다.
이건 “어떻게 시그널이 작동하며, 세그폴트에서도 보내지는 게 해당 시그널이라는 걸 확인하기 위해서” 보여준 것일 뿐이니, 이런 방식으로 세그폴트를 해결하지는 마세요. 그냥 포인터를 다시 점검해보는게 훨씬 바람직합니다.
시그널의 필요성
오케이 알았어요. 근데 왜 대체 이런 게 필요하죠?
- 프로세스를 kill하는 것 외에도, 사용자 정의 시그널들을 사용하여 어떤 일이 일어났는 지 프로세스에게 알려줄 수 있기 때문입니다.“야 내가 너한테 해줘야하는 그 일 지금 끝냈어.”
- 같이 작동하는 2개의 프로세스가 있을 때, 하나의 프로세스가 작업을 끝내고 나서 다른 프로세스에게 이렇게 시그널을 보낼 수 있어요.
- 다른 흔한 케이스 중 하나는, 어떤 안좋은 일이 생겼을 때 시그널을 처리하도록 하는 것입니다.
- kill 되었을 때나, 누군가 ctrl + C를 눌렀을 때나, kill -9 같은 어떤 경우든 간 상관없습니다. 당신은 프로그램이 종료되기 전에 파일을 닫고 메모리를 해제하는 등의 처리를 해주고 싶을 것입니다. 프로그램이 실제로 종료되기 전에 일관적인 상태로 만드는 작업이요. 이런 걸 항상 사용하지는 않겠지만 일단 그렇다고 치자고요. 가끔 ctrl + C 실행 시 취해지는 행동들이 충분하지 않을 수 있습니다. 가끔씩은 아주 장렬히 실패해야할 수도 있죠.
Sigaction 함수
마지막으로 몇 가지만 더 말해볼게요.
저는 예시에서 signal() 함수만 사용해서 설명했습니다. 왜냐면 그게 제일 간단하기 때문이에요. 그렇지만 signal의 기능들을 포함하는 sigaction이라는 더 새로운 함수가 존재합니다. 이건 더 많은 옵션과 정보를 제공해주며, 당신이 시그널들을 관리할 때 프로세스에 대한 더 많은 제어를 가능하게 해줍니다.
그러니 sigaction을 사용한다면 당신의 코드는 좀 더 이식성이 좋아집니다. 그래서 더 추천되는 방식인 거에요.
(man sigaction을 터미널에 입력해 해당 함수의 메뉴얼을 확인할 수 있음)
이건 제가 sigaction을 사용했을 경우의 원본 코드입니다.
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
void handler(int num)
{
write(STDOUT_FILENO, "I won't die\\n", 13);
}
void seghandler(int num)
{
write(STDOUT_FILENO, "Seg Fault!\\n", 10);
}
int main()
{
struct sigaction sa;
sa.sa_handler = handler;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGTERM, &sa, NULL);
while (1)
{
printf("Wasting your cycles. %d\\n", getpid());
sleep(1);
}
}
그나저나, 이쯤되면 여러분은 제가 printf() 대신에 write() 함수를 사용했다는 사실을 눈치 채셨을 거에요. 이거에는 따로 이유가 있습니다.
핸들러들은 비동기적으로 실행되기 때문에, 그것들은 당신의 코드를 어떤 시점에서나 방해할 수 있습니다. 그러니 여러분들은 sigal handler 안에서 어느 코드나 실행할 수 있는 건 아니에요.
standard library에서 몇몇 함수들은 sync signal safe라고 나열되어있습니다. 이건 그 함수들을 signal handler 안에서 실행하기에 안전하다는 뜻입니다. 다른 코드들과 함께 비동기적으로 실행할 수 있다는 것이죠. 그 항목에는 여러가지 함수들이 존재하는데 printf는 그 항목에 존재하지 않네요. 그래도 write()는 존재합니다. 그래서 이걸 사용한거에요. 또 그게 실제로 printf가 사용하는 것이기도 하니까요. 더 투박하긴 하겠지만 안전하잖아요.
그렇지만 signal handler 함수 내에서 printf를 사용했을 때 그게 항상 충돌한다는 뜻은 아닙니다. 그냥 그게 충돌할 가능성이 있고, 항상 안전함을 보장하지는 않는다는 뜻이죠.
그래도 명백한 이유도 없이 랜덤한 시점에 충돌나는 그런 프로그램은 아무도 좋아하지 않을거에요.
지금까지 signal에 대해 설명했습니다.
여러분들은 이걸 모든 프로젝트에 사용하지는 않을 것이고 분명 매일 사용하지도 않을 거에요. 그래도 이젠 signal이 필요한 경우 그걸 사용할 수 있을겁니다.
이 영상이 여러분들의 미래 프로젝트에 도움이 되었기를 바랍니다.
'IT > 튜토리얼 및 가이드' 카테고리의 다른 글
서비스 디자인 (기술 / 기획) 가이드 배포 (2) | 2025.05.02 |
---|---|
[개인적인 팁] 영어 논문 쉽게 읽는 법 (5) | 2022.03.01 |
[입문자 튜토리얼] - C언어 소스 코드 파일 분리 2편 (feat. 헤더파일) (0) | 2021.12.19 |
[입문자 튜토리얼] - C언어 소스 코드 파일 분리 1편 (feat. 코드를 깔끔하게) (0) | 2021.12.19 |
[Github] 깃허브 왕초보 사용법 - 기본편3 (0) | 2021.12.19 |
[입문자 튜토리얼] - C언어 소스 코드 파일 분리 2편 (feat. 헤더파일)
지난 시간에는...
지난 시간에는 어떤 게 알아보기 어려운 코드인지, 그 문제점을 알아보았다. 또 그걸 해결하기 위한 "코드 깔끔하게 짜는 법"을 알아보았다.
"한 파일안에 코드 줄 수가 너무 많다고요? 그러면 나더러 어떻게 하란거에요. 뭐 다른 방법이 있나요?"
오늘은 이 질문에 대한 답변을 하는 시간을 갖도록 한다.
자, 저번에서 그 한 파일에 있던 코드들을 1. 배열을 이용한 함수, 2. 연결리스트를 이용한 함수, 3. 메인함수와 그 외의 함수라는 총 3가지의 분류로 나누어, 각각을 따로 파일에 담았다하자. 그럼에도 아직 문제가 남아있다.
"파일을 여러 개로 나눠요? 그러면 main.c 파일에서 어떻게 다른 파일의 함수를 읽어오나요? 게다가 컴파일은 어떻게 해요?"
사용자 정의 헤더파일
우선, 코드를 길게짜는 사람이라면, 함수의 원형을 main문 위쪽에 선언해주는 방법을 아마 알 것이다.
#include <stdio.h>
void hello(); // 반환값이 없는 hello 함수 원형 선언
int main()
{
hello(); // hello 함수 호출
return 0;
}
void hello() // 반환값이 없는 hello 함수 정의
{
printf("Hello, world!\n"); // Hello, world! 출력
}
main문에서 위쪽에 함수를 선언해주면, 어느 위치에 함수가 오더라도 메인에서 이 함수를 읽어들여 프로그램을 돌릴 수 있다.
파일을 여러개로 나눌 경우에도 마찬가지다. 함수 파일마다 내 전체함수들의 프로토타입과 사용되는 구조체를 전부 상단에 넣어주면 될 것 같다. 근데 그러면 깔끔하지가 않다... 방법이 없을까?
이 경우 쓰게 되는 게 사용자 정의 헤더파일이다.
C언어 기초 - 헤더파일 만드는 방법과 사용하는 방법
본문 목표 프로젝트가 복잡하고 규모가 클 수록, 코드가 많이 길어지게 된다. 코드가 길어지면 가독성이 떨어지게 된다. 가독성이 떨어지면, 코드 개발이 복잡해지고, 오류가 발생할 확률이 높
diyver.tistory.com
위 블로그를 참고하면 좋다.
헤더 파일 예시
#ifndef _EXAMPLE_H_
#define _EXAMPLE_H_
/*
* include할 헤더 목록 적기
*/
typedef struct 구조체 명
{
...
} 구조체;
int 함수1();
int 함수2();
void 함수3();
void 함수4();
#endif
다음과 같은 방식으로 헤더파일에 모든 include할 헤더목록, 구조체명, 내가 사용한 모든 함수의 프로토타입을 적어준다.
해당 파일의 이름을 example.h라고 저장했다고 해보자.
그럼 내가 가진 모든 C 소스 파일의 위쪽에 모두 #include "example.h" 라는 선언을 한줄만 추가해주면 된다.
그럼 모든 파일의 상단에 내가 사용할 구조체&함수들을 전부 선언해놓은 것과 동일한 효과가 난다!
여기에서 #include <example.h>가 아닌, "example.h"로 따옴표를 사용해줘야만 한다. 사용자가 정의한 이런 헤더파일은 원칙적으로 따옴표를 써야하기 때문이다.
그럼 이제, 어떻게 main 파일에서 다른 파일의 함수들을 읽어오냐는 질문에 대한 답변은 끝이 났다.
그러면 이제 남은 질문은?
그렇게 여러 개로 나눠진 파일들을 어떻게 묶어서 컴파일 해요?
이거다.
다음 포스팅에서 이어서 이것을 설명하도록 하겠다.
다음 포스팅에서는 컴파일의 대략적인 과정과, 컴파일러, 컴파일 명령어 그리고 makefile에 대해 배운다.
'IT > 튜토리얼 및 가이드' 카테고리의 다른 글
[개인적인 팁] 영어 논문 쉽게 읽는 법 (5) | 2022.03.01 |
---|---|
[번역] C에서 시그널을 보내고 처리하는 방법 (kill, signal, sigaction) (0) | 2022.01.06 |
[입문자 튜토리얼] - C언어 소스 코드 파일 분리 1편 (feat. 코드를 깔끔하게) (0) | 2021.12.19 |
[Github] 깃허브 왕초보 사용법 - 기본편3 (0) | 2021.12.19 |
[Github] 깃허브 왕초보 사용법 - 기본편2 (0) | 2021.12.19 |
[입문자 튜토리얼] - C언어 소스 코드 파일 분리 1편 (feat. 코드를 깔끔하게)
서론
사실 이 포스팅을 쓰게 된 것에는 깊은 사연이 있다... 얼마 전 지인의 팀플 코드를 같이 디버깅해본 적이 있다. 이때 나는 약간 충격을 받았다. 코드가 어려워서? 그것도 조금은 있겠지만.... 제일 큰 이유는 한개의 소스 파일에 1200줄 이상 들어있는 코드와...기능이 각기 다른 수십 개의 함수가 main.c라는 한 개의 파일에 뒤섞여서 코드의 흐름을 알아볼 수 없었기 때문이다.
특히나 나는 그 코드를 같이 짠 것도 아니고 처음 읽는 입장이니까 더욱 코드를 파악하기 어려웠다. 코드 파악에만 몇 시간이 걸렸다.
사실 예전의 나는 오히려 그것보다 훨씬 코드를 정말 어지럽게 짜고 함수를 나누지 않았기 때문에... 내가 절대 뭐라할 수 없는 일인 것 안다. 그렇지만 코드를 깔끔하게 짜는 법은 절대 학교에서 누군가 가르쳐주지 않더라...
따라서 내 소박한 지식을 나눠보고자 포스팅을 쓴다.
아직도 난 많이 부족하겠지만, 그래도 내가 거쳐온 과정을 통해 최소한 코드를 분류하고, 정리하고, 파일과 함수를 나누는 법은 잘 숙지하게 되었다고 생각한다. (실제로 내가 활동 중인 42서울 코드 규정에는 함수 개당 길이 제한, 변수 개수 제한 등등 까지 있다)
더보기
코드 문제점 파악
해당 과제는, 한 txt 파일을 읽어와서 그 안의 데이터베이스를 검색-삭제-추가하는 그런 프로젝트였다. 여기에서 모든 기능을 각각 배열과 연결리스트로 둘다 구현해야하는 그런 것이었다.
일단 문제상황이 어떤 느낌이었는 지 대략 의사코드로 함수를 써보겠다..
#include <헤더>
#include ...
..
배열_검색_3()
링크드리스트_데이터추가2()
링크드리스트_출력()
배열에_데이터 추가2()
배열_검색_2()
배열_데이터추가1()
링크드리스트_검색2()
링크드리스트 어쩌고3()
배열검색어쩌고1()
링크드리스트 어쩌고2()
배열_출력()
.... 등등 수십개의 함수
int main()
{
... (100줄이 훨씬 넘는 메인문)
return (0)
}
이 코드의 문제점은 대략 이렇다.
- 배열과 관련된 함수들은 그들끼리, 연결리스트 관련 함수는 그것들끼리 모여있어야 보기 편한데, 여기엔 배열이나 연결리스트 관련 함수가 순서 상관없이 마구 뒤섞여있다.
- 배열_검색() 관련 함수는 검색 함수1, 2, 3끼리 위아래 붙어서 모여있어야 보기 편한데, 관련 함수들이 위 아래 중간 할 것 없이 수십개의 함수 사이에 숨어서 무차별적으로 분포한다.
- 배열을 검색하는 기능을 가진 함수들을 차례차례 찾아서 살펴보는 것 자체가 미로찾기 수준이다. 하나를 찾으면 다음 함수를 찾으려고 코드를 샅샅이 뒤지는 과정을 반복한다.
- 이때 코드 흐름을 놓치기 쉽다. 그러면 처음부터 다시 읽기 시작해야한다....(오마이갓)
- 배열을 검색하는 기능을 가진 함수들을 차례차례 찾아서 살펴보는 것 자체가 미로찾기 수준이다. 하나를 찾으면 다음 함수를 찾으려고 코드를 샅샅이 뒤지는 과정을 반복한다.
- 일단 main이 너무 밑바닥에 존재해서 너무 읽기가 힘들다. 게다가 설사가상으로 메인 함수까지 굉장히 길었다.
- main 함수조차 너무 길고, 흐름이 분류되있지 않아서 파악이 힘들었다.
이러면 어떤 문제가 생기는 가?
- 코드를 짠 사람이 아니라면 그 누구라도 코드를 파악하기 힘들다.
- 코드에 문제가 생겼을 때 어느 부분인지 찾는 게 힘들다.
- 심지어 문제가 난 부분을 알더라도 위쪽으로 한참 이동해서 해당 함수를 살피다가~ 아래쪽 끝까지 메인으로 내려와 메인을 고쳐 다시 실행해보고~ 이러는 데 불필요한 시간이 엄청나게 소요된다.
- 메인문을 봐도 코드의 흐름 자체가 안보인다.
좋은 프로그래머의 요건
실제 프로그래머는 혼자서 일을 하지 않는다. 사람이기 때문이다. 작은 프로젝트 정도는 혼자 할 수 있겠다. 그런데 회사에서 그리고 사회에서 요구하는 건 큰 프로젝트다. 그러니 필연적으로 누군가와 일을 분담해서 하게 될 수 밖에 없다. 심지어 프리랜서라고 해도 그 일감은 회사나 업체의 큰 일을 나눠받아서 하는 것이다.
이때 코드를 남이 파악하기 어렵게 짜버린다면 어떻게 되겠는가. 당신의 코드를 받은 뒤 프로젝트의 나머지 부분을 이어서 만들어야하는 동료가 많이 곤란해진다.
코드를 어렵게 짠다는 것은 결코 바람직하지 않다. 실력이 좋은 프로그래머는 이해하기 쉬운 깔끔하고 간단한 코드를 짠다. 항상 남이 읽을 경우를 염두에 두고 코드를 깔끔하게 만드는 연습을 해야한다.
이 문제 상황을 통해 어떻게 코드를 구성하면 보기 좋고 깔끔한 지 구상해 볼 수 있다.
그 방법은 다음과 같다.
코드 깔끔하게 구성하는 법
위의 문제상황에 있는 문제점들을 정확히 반대로 뒤짚으면 그 해결책이 된다.
바닥에 쌓여있는 책들을 도서관 책장에 정리한다고 생각하며 이 방법들을 읽어보자.
- 배열-연결리스트 관련 함수들이 순서 상관 없이 마구 뒤섞여 있다.
- 해결책 : 배열관련 함수는 배열 관련 함수끼리, 연결리스트 관련 함수는 연결리스트 관련 함수끼리 순서를 묶어서 정리한다.
- 배열_검색() 함수들이 코드 여기저기 멀찍멀찍 아무데나 분포한다.
- 해결책: 비슷한/같은 기능을 하는 함수들끼리 위아래로 붙어있게끔 모아서 정리한다.
- 메인 문이 너무 길다 :
- 해결책 : main을 깔끔하게 짜려면 다음 방법을 써야한다. 흐름을 명시적으로 나타내는 함수명을 가진 함수들로 기능을 나눠 코드를 나눠담는다. main의 코드 줄 수는 무조건 짧게 유지하는게 좋다. 무조건이다.
함수는 너무 길지 않게 만드는 것이 바람직하다. 안된다면 그 안의 자잘한 기능들/조건문 같은 것들을 또다른 작은 함수로 빼서 최적화시켜라.
파일 나누기
자 이제 코드를 분류 별로 기능별로 순서를 묶어 정리했다고 해보자. 그런데 아직도 한 파일에 코드가 너~~~~무 많이 들어있다...
만약 회사일으로 프로그래밍을 한다고 가정해보자.
당신은 몇 천줄 몇 만줄의 소스코드를 짯다. 그리고 한개의 소스 파일에 그 코드를 전부 넣어두었다. 그런데 이 몇 만줄이나 되는 코드에서 문제가 난다. 그러면 심지어 간단한 문제라 할지라도, 문제를 찾기가 정말정말 오래 걸릴 것이다.
코드를 위로 갔다 아래로 갔다 메인과 위쪽 함수들을 번갈아 위아래로 쉐킷쉐킷하며 읽는다. 그러면 간단한 문제 하나 찾지 못하고, 코드와 함수간에 스크롤로 이동하는데만 99%의 시간을 뺏기게 될 것이다.
"그러면 나더러 어떻게 하란거에요. 뭐 다른 방법이 있나요?"
있다!
바로 파일을 여러 개로 나누는 것이다.
저 팀프로젝트 코드의 경우에, 연결리스트 관련 함수는 use_Linkedlist.c, 배열 관련 함수는 use_Array.c 라는 파일에 나눠담는다고 해보자. 그리고 그 이외의 함수와 메인문은 main.c에 담는다.
이런 경우, 함수를 파악하기 엄청 수월해진다.
"파일을 여러 개로 나눠요? 그러면 main.c 파일에서 어떻게 다른 파일의 함수를 읽어오나요? 게다가 컴파일은 어떻게 해요?"
바로 사용자 헤더파일을 만들어 모든 파일 상단에 선언해놓는 것이다. 그리고 그 여러개의 파일들을 함꺼번에 컴파일하려면 명령어를 사용하거나, makefile을 사용하면 된다.
이대로는 너무 포스팅이 길어질 것 같으니 다음 편에 이어서 파일 나누기 (헤더파일 만들기, Makefile이 무엇인지)를 이어서 설명하도록 하겠다.
'IT > 튜토리얼 및 가이드' 카테고리의 다른 글
[번역] C에서 시그널을 보내고 처리하는 방법 (kill, signal, sigaction) (0) | 2022.01.06 |
---|---|
[입문자 튜토리얼] - C언어 소스 코드 파일 분리 2편 (feat. 헤더파일) (0) | 2021.12.19 |
[Github] 깃허브 왕초보 사용법 - 기본편3 (0) | 2021.12.19 |
[Github] 깃허브 왕초보 사용법 - 기본편2 (0) | 2021.12.19 |
[Github] 깃허브 왕초보 사용법 - 기본편1 (1) | 2021.12.19 |
[Github] 깃허브 왕초보 사용법 - 기본편3
지난 시간에는 vscode와 git의 설치, 그리고 git을 통한 깃허브 업로드 방법에 대해 알아보았다. 사실 왕초보 포스팅이라서 쉽게 만드느라 못 적은 내용들이 정말 많다고 생각한다. 그렇지만 더 적어봤자 초보한테는 귀에 들어오기는 커녕 더 학습이 안되기 마련이기 때문에... 그나저나 쉽게 만들려고 노력했는데 과연 그런지 잘 모르겠다.
어려운 내용이 있거나 궁금한 내용이 있다면 댓글 주십시오.
하여간 이번 포스팅 이어서 시작한다.
이번 편에서는 fork와 github를 통한 검색, 그리고 깃허브 프로필 관리를 다룬다.
이번 편은 쉽다. 그러니 편하게 시작합시다~
fork 가 뭐죠... 숟가락 그 다음에 포크인가요?
남이 올린 레포지터리로 들어가봤다. 저기 빨간 네모박스 표시된 쪽에 fork라고 되있는데, 이걸 한번 클릭해보겠다.
그러면 위와 같은 화면이 뜬다. 저기에서 seo-a-nam (내 깃허브아이디)를 클릭해준다.
오오... 그러니까 내 레포지터리 목록에 저게 똑같이 생긴다.
클릭해보면 다음과 같이 나오며, 레포 이름 아래에 작게 누구누구로부터 fork해왔어요...하고 적혀있다.
이를 통해, fork는 남의 레포지터리 사본을 내 레포지터리로 가져오는 기능이라고 볼 수 있다.
음식을 포크로 콕 찍어서 내 접시로 덜어온다고 생각하면 이해하기 쉬울 것 같다.
보통 github에서 내가 내 레포지터리 권한 목록에 상대를 추가하지 않는 이상, 내 레포지터리는 남이 수정할 수 없다. public 레포지터리 (공개 레포지터리)인 경우에는 남이 코드를 git clone으로 다운로드받을 수는 있어도, 그 레포지터리를 변경시킬 수 없다는 얘기다.
이때 fork 기능을 사용해서 자기 레포지터리로 사본을 받아오면, 해당 내용을 수정하고 자기 맘대로 작업할 수 있게된다. 원본이 변경되지 않으면서도 해당 레포를 본인 레포로 가져와 쓸 수 있으니 유용하다 볼 수 있다. 그래서 협업 기능으로서도 잘 쓰인다고 한다.
깃허브에서 남의 코드를 어떻게 볼 수 있나요? 남들도 제 코드를 볼 수 있는건가요?
깃허브의 주된 기능 중의 하나다. 바로 검색!
이걸로 족보나 아니면 내가 만들고싶은 프로그램 관련 코드도 찾을 수 있으니.. 정말 유용하다 볼 수 있다.
특히 대학생들은 이걸로 족보를 많이 찾더라.
일단 지금 바로 해보도록 한다. 난 minitalk이라는 과제를 검색해보고 싶다. 내 프로필 페이지로 들어가 왼쪽 상단의 검색창에 내용을 입력한다.
주의할 점은, 본인 깃허브 프로필 화면에서 저 검색 기능을 사용하면 본인이 올린 것 중에서만 해당 내용을 찾게된다는 단점이 있다. 저렇게 검색이 들어간다.
뭐 이럴 때도 그냥 앞에 내 아이디 부분 지워주고 All Gihub로 모든 게시글 검색을 눌러주면 된다.
890개의 관련 레포지터리, 그리고 5천개가 넘는 코드들이 검색되었다. 그냥 곳간이 따로 없다. 이 자료들을 보며 열심히 찾으면 원하는 자료가 나올 확률이 아주 높다.
"그러면 남들도 제 코드를 볼 수 있지 않나요? 전 보여주기 싫은데..."
충분히 그럴 수 있다. 다행히 레포지터리는 private/public 이라는 공개 범위 설정이 있다. private 레포지터리를 만들면 비공개로 올릴 수 있는 것이고, public으로 올리면 남들도 열람이 가능한 것이다.
생성할 때부터 public/private을 설정하고 만들 수 있고, 이미 만든 레포지터리의 공개범위를 바꿀 수도 있다.
1. 생성할 때부터 공개범위 설정하기
여기 생성할 때부터 public 혹은 private으로 설정할 수 있도록 선택 옵션이 주어져있다. 본인 맘에 따라 설정하고 레포를 만들면 된다.
2. 이미 있는 레포지터리 공개범위 변경하기
레포지터리 -> settings -> 맨 아래로 내려줌 - Danger Zone 에서 "Change visibility" 눌러준다.
그럼 다음과 같은 화면이 뜨면서 해당 레포의 공개범위를 변경 가능하다.
깃허브 프로필이 너무 휑해요.... 남들은 화려하던데 그거 어떻게 하는 건가요?
깔끔하고 이쁘게 된 페이지나 프로필은 남에게 인상을 주기도 쉽고, 나의 기술스택이나 나의 관심사, 나의 연락처 등등 나에 대한 소개를 잘 전달하기 정말 좋다.
지금 현재 내 페이지는 다음과 같다. (프로필로 되있는 그림은 내가 작년에 휘리릭 갈긴 낙서다)
보통 계정을 처음 만들면... 프로필 사진도 기본 사진에 그냥 저런 소개 페이지고 뭐고 없이 엄청 휑~하다. 내 깃허브에도 프로필 아래 한줄 소개란 말고는, 내 소개글을 올릴만한 공간도 없다.
그럼 저런 소개페이지는 어떻게 해야 만들 수 있는 걸까?
바로, 레포지터리를 하나 만들면 된다. 이때, 레포지터리 이름은 반드시 본인 아이디와 같은 레포를 만들어야한다. 그리고 거기에 README.md 파일을 추가해서 html같은 마크업언어로 편집해주면 저렇게 리드미파일이 프로필 메인에 보이게 된다. html로 로고 만들면서 저기 로고에 하이퍼링크로 링크를 넣어주면 클릭했을 때 내 블로그 페이지나 인스타 페이지로 이동할 수 있도록 해줄 수도 있고, 정말 신기하다.
이게 무슨 얘기지 싶겠지만 다음 링크들을 클릭해서 하는 대로 하나하나 해보면 님들도 멋진 깃허브 프로필을 만들 수 있을 것이다.
https://80000coding.oopy.io/865f4b2a-5198-49e8-a173-0f893a4fed45
깃허브 프로필 꾸미기!
깃허브에 들어갈 때마다 허전한 내 프로필..
80000coding.oopy.io
http://blog.cowkite.com/blog/2102241544/
Github Profile 꾸미기
개발요정 김소연 블로그 🧚♀️
blog.cowkite.com
위 링크들에 더 자세한 내용들이 나와있으니, 참고하여 예쁜 프로필을 꾸며보자~
참고로 README.md로 만드는 저런 프로필 소개 페이지 기능은 작년에 출시된 기능이라고 한다. 나는 올해에서야 알게되었지만 ㅋㅋ 하여간 지금이라도 알게되서 다행이다.
나는 아직 관심분야를 잘 못정해서 관심분야를 못적어놨지만, 저기에 내 관심분야는 ~ 이런 것도 적어두면 정말 좋다.
이렇게 내가 설명하고 싶은 필수 내용들은 기본편을 통해 다 설명한 것 같다. 깃허브를 통해 다른사람과 협업하는 등 그런 내용들은 나중에 시간이 나면 심화편에 추가로 정리하고 싶다.
나는 깃허브를 사용하는 습관을 일찍 못배운 걸 되게 후회하곤 한다...그동안 날린 코드도 많고. 그러다 보니 내가 들여다보며 복습할 수 있는 코드도, 내가 보여줄 수 있는 결과물들도 훨씬 적어졌다. 내 포스팅을 본 사람들은 다들 일찍부터 잘 정리하길 바란다. 코드는 차곡차곡 정리하며 복습하면 정말 남는게 자산이다....
그럼 이번 포스팅을 마친다.
'IT > 튜토리얼 및 가이드' 카테고리의 다른 글
[입문자 튜토리얼] - C언어 소스 코드 파일 분리 2편 (feat. 헤더파일) (0) | 2021.12.19 |
---|---|
[입문자 튜토리얼] - C언어 소스 코드 파일 분리 1편 (feat. 코드를 깔끔하게) (0) | 2021.12.19 |
[Github] 깃허브 왕초보 사용법 - 기본편2 (0) | 2021.12.19 |
[Github] 깃허브 왕초보 사용법 - 기본편1 (1) | 2021.12.19 |
[번역] 가상화(virtualization)란 무엇일까요? (0) | 2021.11.15 |
[Github] 깃허브 왕초보 사용법 - 기본편2
지난 포스팅에는 깃이란 무엇인지, 깃에서 기본적으로 알아야하는 용어가 무엇인지 정리해보았다.
근데 지난번꺼는 사실 다 의미없다. (예...?)
그러니까 내 말은, 백번 들어봤자 한번 해보는 것만 못하다는 얘기다!
이 포스팅을 보며, 꼭 직접 따라해보며 차근차근 날 따라오시라.
이번 편에서는 vs코드와 터미널을 사용해서 깃허브에 코드를 올리는 법을 소개한다.
사실상 가장 중요한 파트다!!!!!! 직접 해봐야하는 부분이니, 무조건 하나하나 해보며 따라와라.
노트북 준비!! 보면서 열심히 따라해야하니 손가락 스트레칭 미리하고 오시오!
(왕초보한테는 시간이 걸리는 게 당연한거다. 인내심을 가지고 끝까지 따라해보자.)
깃허브에 코드를 올리고 싶어요
깃이고 깃 용어고 뭐고 다 필요 없다. 결국 우리의 목적은 깃허브에 코드를 올리고 관리하는 거다.
처음에 깃허브를 시작하는 목적은 다들 비슷하다. 협업이나 그런 것에 앞서서, 주로 자기 코드를 올려서 보관하고, 포트폴리오처럼 가꾸고, 남의 코드도 구경하기 위함이 아닌가?
본론으로 돌아가서, 깃허브에 코드를 올리는 방법은 3가지가 있다.
(일단 깃허브 회원 가입-로그인은 미리 하고 와라)
모든 방법에 앞서, 일단 레포지터리를 만들어야한다.
먼저 프로필에서, 상단 바의 Repository 라는 메뉴를 클릭해준다. 아래 사진에서 아래에 빨간 선 그어져있는 메뉴이다.
그럼 레포지터리 목록이 뜨는 데, 이때 저 New 버튼을 눌러서 새 레포지터리를 생성해줄 수 있다.
New 버튼을 누르니 위와 같은 화면이 나온다. 저기 Owner 이름 옆에 Repository name 이라고되있는 칸이 보이는가? 여기에 새로 만들 레포 이름을 적어준다. 그냥 바탕화면에 새로운 폴더 추가 - 이름 지어주기 이런 과정과 똑같다고 봐도 무방하다. 중복되지 않은 이름을 지어준 후, 맨 밑의 "Create repository" 버튼을 눌러주자.
일단 레포를 생성했으면 아래와 같은 화면이 뜬다.
이제부터 우리의 작업이 시작된다. ((두둥))
깃허브에 코드를 올리는 3가지 방법 (각자 다름)
1. 드래그-드롭으로 올린다.
2. 터미널에서 명령어 사용1 - git init -> git remote add origin "레포 주소" -> git push
3. 터미널에서 명령어 사용2 - git clone -> git add -> git push
1. 드래그-드롭으로 업로드한다
가장 쉬운 방법이다... 그런만큼 여러 단점이 존재한다..
레포를 처음 생성한 아까 그 상태에서, 저 빨간 박스에 있는 것 중 "uploading an existing file"을 클릭해보았다.
그리고 choose your files를 클릭해 파일을 업로드하거나 아니면 직접 드래그-드롭하여 예시 파일을 업로드 해주었다.
commit changes를 눌러 작업을 완료한다.
그럼 다음과 같이 업로드가 완료된다. 이 방법은 가장 간단하다.
그러나 이 방식으로는 나중에 파일의 수정/삭제가 많이 불편하다. 또 이 방법만 사용하다보면, 여기 파일들을 폴더 안으로 옮겨서 정리하거나하는 그런 이동 작업들이 아주 힘들어진다. 자유롭고 편한 작업을 위해서는 명령어로 업로드하는 법을 반드시 알아놓아야한다.
2. 터미널에서 명령어 사용1 - git init -> git remote add origin "레포 주소" -> git push
"터미널 사용? 명령어?? 이게 다 뭐냐... 이번엔 진짜 관둬야겠다."
이런 생각을 하고 있는 친구들이 꽤 많을 것이라 생각한다.....나 역시 그랬다.
근데 지금 이 명령어 달랑 몇 개만 외워두면 나중이 아~주 편해진다. 노후대비마냥 든든해진다... 진짜 날 믿어라!
특히 올리고 수정하고 그러는 파일이 많아질수록, 저 명령어들은 진정한 빛을 발한다.
자 그럼 시작한다.
참고로 터미널은 명령어를 칠 수 있는 어떤 검은 화면.. 그런 것이라 생각하면 된다.
사전 준비 : git 설치, vscode 설치 (아래 더보기 누르기)
git 명령어를 사용하기 위해서는 먼저 컴퓨터에 git을 설치해야하겠다.
mac(애플)환경과 Window환경에 대해 git을 설치하는 방법은 다음 2개의 링크로 각각 알아볼 수 있다. 각자의 시스템에 맞는 링크를 클릭하여 git 설치를 해주자.
Mac Os 환경에서 Git 설치하기 / homebrew 설치
🌕 개발자라면 git과 github를 다루는데 익숙해야 한다고 하는데 공부할 일이 없다가 이번에 스터디를 하며 드디어 스터디원들과 함께 개발하며 github를 이용한 협업을 경험할 것 같다!! 😄 그 중
hanco.tistory.com
https://coding-factory.tistory.com/245
[Git] 윈도우 Git 설치하기 (Git for Windows)
GIt을 사용하려면 먼저 Git이 PC에 설치되어 있어야합니다. Git설치방법에 대해 알아봅니다. 윈도우버전 Git설치하기 1. Git 설치파일을 다운로드 받습니다. 아래에 링크되어 있는 페이지에 들어가서
coding-factory.tistory.com
우리는 위 링크를 이용해 깃을 설치했고, git bash를 실행하여 git config로 유저명, 유저이메일 설정까지 해준 상태가 되었다. 이젠 아주 든든~하다. 이걸로 터미널(검은 화면 같은거)에 명령어만 타닥 쳐주면 내 코드가 알아서 깃허브에 올라간다.
그런데 이때 훨씬 더 편하게 쓸 수 있는 방법이 존재한다!
그건 바로, 우리가 코드를 쓰고 편집하는 에디터에서 바로 올려주는 거다.
놀랍게도, vscode라는 편한 에디터에선 그게 가능하다! 여기에도 터미널이 붙어있기 때문이다.
이건 진짜 엄청 많은 개발자들이 사랑하는 개발도구다. 꼭! 깔기를 추천한다. 테마까지 적용하면 알록달록 아주 이쁜게 갑자기 코딩할 맛이 나기 시작한다. 게다가 liveshare같이 남을 내 코드스페이스로 초대해서 같이 동시코딩하는 확장팩 기능도 있고... 진심 잘 활용하면 엄청나진다. 기회가 된다면 vscode의 사용법 및 활용법도 포스팅하고 싶다.
vscode가 없다면 다음 링크를 눌러 지금 설치하자.
https://code.visualstudio.com/
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.
code.visualstudio.com
단축키 ctrl + '~' 을 눌러주면 하단에서 저렇게 터미널이 뿅 튀어나온다. 저기다가 명령어를 입력해주면 내 코드들을 바로 올려줄 수 있다는 거.... (와~신난다~)

참고로 이건 윈도우에 있는 vs코드다.
방금 윈도우에서 vs코드를 깐 사람은 알거다. 사실 저 사진에는 함정이 숨어있다...
내 예상컨데, 지금 막 vs코드를 깔은 님들은 윈도우 파워쉘 터미널을 쓰는 중이다. bash shell 터미널로 바꾸자.
다음 링크를 클릭해서 작업을 완료해주면 윈도우에서도 나와 같은 터미널을 볼 수 있을 것이다.
(참고로 mac 운영체제에서는 원래부터 bash 쉘을 기본 터미널로 쓰기 때문에 따로 바꿔줄 필요없다.)
https://grahams.tistory.com/353
[vsCode]윈도우 powershell => git bash 로 바꾸기
윈도우를 쓰는 분들이라면 vs code에서 터미널을 켜면 powershell 이 나올겁니다. 하지만, 저는 약간 무거운 감이 있어 bash를 선호합니다. 맥도 사용하는 저로서는 되도록 동일 환경이 좋아서이기도
grahams.tistory.com
git 설치부터 vs코드 설치까지... 사전준비는 이제 진짜 다 끝났다.
~ 그럼 이제 본격적인 명령어 입력 시간이다~
알아둬야 할 "터미널 기본 명령어" 모음
모든 명령어는 타이핑 후에 엔터를 쳐서 입력한다
1. pwd : 현재 위치(디렉토리)를 확인
2. ls : 현재 디렉토리에 존재하는 파일, 폴더 목록을 확인
3. cd (폴더명) : 해당 폴더 안으로 들어간다.
4. cd .. : 해당 폴더에서 이전 디렉토리로 나온다.
나는 막 바탕화면에 example이라는 폴더(폴더 이름은 아무거나 상관 없다)를 만들었다. 그 안에는 예시 코드 파일들이 들어있다. 이걸 올리고 싶다.
그럼 어떻게 해야하는 지 보여주겠다.
그냥 터미널이던 vscode의 터미널이던 상관없다. 터미널의 종류도 상관 없다. 일단 님들의 터미널을 지금 당장 켜라!
일단 지금 위치를 확인(pwd 입력)하고 그다음 Desktop(바탕화면) 위치로 이동해준다. cd는 change directory의 약자로, 이 디렉토리(폴더)에서 안에 있는 저 디렉토리(폴더)로 들어가겠다 이 말이다. 반대로, 뒤로 빠져나오고 싶을때는 cd .. 을 입력해주면 된다.
그 다음 바탕화면에 있는 example 폴더로 이동한다. 그 폴더 안에서 ls로 현재 파일목록을 보니 코드 파일이 3개 있다.
여기서부터 우리가 알아야할 명령어가 나온다. 꼭! 지금 바로 vscode나 터미널을 켜서 따라해보아야한다. 그러면 백날 눈으로 보는 것보다 훨씬 잘 이해된다.
1. git init
git init이라는 명령어의 뜻은 "지금 이 폴더를 깃이 관리해주세요~"하는 것이다. 즉, 깃에 대한 초기화 작업이다. 우리가 가진 일반 폴더를 깃을 통해 업로드하려면 꼭 해줘야하는 첫 단계이다.
2. git remote add origin (레포지터리 주소)
git remote add origin (레포 링크)는 "제 목적지는 이 레포에요~여기로 업로드할 거에요~"라고 올라갈 목적지를 명시해주는 명령어다.
먼저 레포 링크를 복사해왔다. 그 다음 터미널에서 git remote add origin (레포 링크)를 입력해주었다.
git remote -v를 이용해서 다시 확인해봐도 잘 설정된 것을 알 수 있다.
3. git add *
"이 폴더 안의 모든 파일을 git이 관리하는 목록에 추가합니다~"라는 명령어다.
파일을 따로따로 추가하려면 'git add (파일명)'을 해주면 해당 파일만 git에 추가된다.
위의 실행화면을 보면, git add * 후에 git status를 실행하여 확인해주니, 세 파일 전부 git에 잘 추가된 것을 볼 수 있다.
4. git status
지금 어떤 파일들이 git에 의해 관리되는 지와 같이 상태를 볼 수 있다. (그냥 확인해주는 정도의 용도다)
5. git commit -m "적고싶은 커밋 메시지"
참고로 커밋(commit)은, 지금 상태/버전을 사진찍듯이 체크포인트 만들어 저장한다는 거다.
-m 옵션을 줘서 지금 당장 커밋메시지를 입력하지 않고 git commit만 입력하더라도, 무슨 커밋메시지 쓰라고 편집창이 따로 뜨기 때문에 귀찮다.
-m "커밋메시지"를 해주면 바로 커밋이 되서 편하다. 깃 커밋을 꼭 해줘야만 이 다음 단계인 깃푸시(업로드)가 된다.
6. git push
이제 올린다! 무슨 에러가 떠서 보니까 git push --set-upstream origin master을 입력하라한다. origin branch를 master브랜치로 설정해서 푸시한다는 뜻이다. 일단 이거 한번만 설정해주면 다음부턴 git push만 해도 쭉쭉 잘 올라갈 거다.
일단 입력해줬다. 그러니 처음엔 갑자기 안올라가고 가만히 있는다. 이때 github에서 vscode를 승인하시겠습니까? 이런 창이 뜬다. 이때 ok 해주고 그러니 잘 올라갔다.
3. 터미널에서 명령어 사용2 - git clone -> git add -> git push (훨씬 더 쉬운 방법)
이번 방법은 유용하다. 빈 레포를 생성한 직후에 처음 업로드 할 때도 쓸 수 있고, 이미 만들어 올린 파일들이 있는 상태에서도 모두 쓸 수 있다.
일단 시작해보자.
먼저 저 code라는 초록블럭을 눌러 저기 나오는 링크(레포주소)를 복사해준다.
1. git clone (레포주소)
깃클론은 "저 레포를 그대로 복사해서 내려받아주세요~"라는 뜻이다. 이때는 깃으로 내려받음으로써 이미 깃이 관리하는 상태이기 때문에 git init을 하지 않아도 되서 편하다는 장점이 있다. 또 이미 내려받은 주소가 있기 때문에, 그 부분을 목적지로 push 해주게 된다. 따라서 git remote로 업로드할 목적지 설정을 할 필요도 없다.
그래서 그냥 git clone (레포주소)라고 쳐서 깃클론 받으려 했더니 현재 데스크탑에 example이라는 이름의 폴더가 존재한다고 튕겼다. 그래서 example2라는 이름으로 내려받아주었다. "git clone 레포주소 폴더명" 이렇게 입력하면 지정한 폴더명으로 내려받아진다. 이 폴더명은 무엇이든 상관없다. 어차피 깃허브의 내 레포 이름에는 영향을 안준다.
2. git add -> git commit -> git push
git add * 를 했을 때, 변경된 파일만 깃에 추가가 되는 것도 확인할 수 있다.
하여간 저 명령어들만 다다다 입력해주면 끝이다. 사실 난 코드를 올리는 3가지 방법 중 git clone을 통한 마지막 방법이 훨씬 간단하고 좋다 생각한다.
빈 레포에 처음으로 뭘 업로드할 때도 그렇고, 다른 컴퓨터에서 내 작업중인 파일을 받아서 작업하기도 편하고, 여러모로 쉽다. 난 그냥 애초부터 이 방법을 통해서 모든 파일을 업로드-다운로드한다. 깃remote는 사실 쓰기 불편하다 ㅋㅋ
"그럼 매번 코드를 올릴 때마다 저 모든 과정을 다해줘야하는 건가요?"
아니. 그럴 필요 없다.
일단 해당 폴더에서 git clone 또는 git init + git remote가 한번이라도 된 상태라면, 다음부터는 그냥 git add -> git commit -> git push만 해도 변경사항이 빠르게 업로드 된다.
또한 git 으로 관리되는 폴더에서는 그 안에서 계속 코드를 수정해도 git add * 하면 수정된 부분만 add 된다. 그래서 저렇게 수정한 부분만 커밋 되서, 내가 올린 커밋메시지와 올린 시각을 확인하면 어떤 부분을 새로 추가하거나 수정했는 지 알기가 편해지는 것이다.
그러니 해당 폴더 안에서 계속 작업해가며 업로드해도 되고, 바뀐 내용 확인하기도 정말 편하다.
아 그리고, 커밋을 하면 내 페이지 메인에 있는 이런 표가 초록색으로 칠해진다. 커밋한 날짜에 해당하는 칸에 저렇게 초록색 표시가 생기고, 커밋을 많이 하면 할수록 진한색으로 바뀌는 것이다. 그래서 이걸 주로 "잔디밭을 깐다"라고도 말한다. 매일매일 코드를 올리면서 저런 기록을 남기는 것만으로도 성취욕구를 자극할 수 있어 좋다는 것이다.
하여튼 이번 포스팅은 대략 이렇게 마무리할 수 있다.
그 외에도 vscode에서 코드를 컴파일하는 법, 확장팩 또는 테마를 설치하는 법은 구글에 치면 바로 나오니 잘 참고해서 순조로운 코딩생활 누리길 바란다~
'IT > 튜토리얼 및 가이드' 카테고리의 다른 글
[입문자 튜토리얼] - C언어 소스 코드 파일 분리 2편 (feat. 헤더파일) (0) | 2021.12.19 |
---|---|
[입문자 튜토리얼] - C언어 소스 코드 파일 분리 1편 (feat. 코드를 깔끔하게) (0) | 2021.12.19 |
[Github] 깃허브 왕초보 사용법 - 기본편3 (0) | 2021.12.19 |
[Github] 깃허브 왕초보 사용법 - 기본편1 (1) | 2021.12.19 |
[번역] 가상화(virtualization)란 무엇일까요? (0) | 2021.11.15 |