Chapter 5. 개발 환경 구축
보안 프로그램도 다 깔았다. GitHub 권한도 받았다. 개발 서버도 접속했다. 이제 정말로 회사 소스 코드를 내 컴퓨터로 가져올 차례다.
팀장님이 슬랙으로 메시지를 보냈다.
"backend-api 저장소 클론받아서 README 읽어보세요. 내일 오전에 코드 리뷰하면서 설명드릴게요."
손이 떨린다.
터미널을 연다. 검은 화면이 나를 바라본다. 커서가 깜빡인다.
'git clone... 그 다음에 뭐였더라?'
학교 때는 수십 번 했던 거다. 과제 저장소 클론받고, 팀플 저장소 클론받고. 그런데 지금은 다르다. 이건 진짜 회사 코드다. 실제 서비스를 돌리는 코드다. 수백만 명이 쓰는 서비스의 심장부다.
GitHub에서 저장소 주소를 복사한다.
https://github.com/company/backend-api.git
'SSH로 해야 하나? HTTPS로 해야 하나? 어디에 클론받지? 홈 디렉토리? 아니면 따로 workspace 폴더 만들어야 하나?'
심호흡을 한다. 괜찮다. 천천히 하면 된다.
GitHub 조직 페이지에 들어간다. 저장소 목록이 쭉 보인다.
backend-api,
frontend-web,
mobile-app,
data-pipeline,
infrastructure...
팀장님이 말한 backend-api 를 클릭한다. README가 펼쳐진다. 기술 스택이 나열되어 있다. Node.js, Express, PostgreSQL, Redis. 'Node.js 20? 내 컴퓨터엔 18이 깔려있는데... 버전도 맞춰야 하나?'
일단 나중 문제다. 먼저 클론부터 받자. 우측 상단에 초록색 "Code" 버튼이 있다. 클릭하면 주소가 나온다. HTTPS 주소와 SSH 주소 두 개가 보인다.
HTTPS는 설정이 간단하다. 바로 사용할 수 있다. 하지만 매번 비밀번호를 입력해야 한다. SSH는 한 번 설정하면 비밀번호 입력이 필요 없다. 이미 SSH 키도 등록했으니까.
'SSH로 가자.'
SSH 주소를 복사한다.
터미널에서 홈 디렉토리에 있다. 그냥 여기에 클론받으면... 나중에 저장소가 여러 개 생기면 지저분해질 것 같다. workspace 폴더를 만들기로 한다. 깔끔하다. 이제 여기에 회사 프로젝트들을 모아둘 수 있다. 필자는 항상 드라이브 루트에 사용하는 아이디나, 닉네임으로 폴더를 만들고 workspace를 만든다 예를 들면 c:/gocoder/workspace 이렇게하면 내가 만드는 모든 폴더를 한 곳에 모아둘 수 있기 때문에 편리하다.
손가락이 멈칫한다.
'이거... 잘못하면 어떡하지? 회사 코드를 내 컴퓨터로 받는 건데... 실수하면?'
괜찮다. git clone은 읽기 전용이다. 저장소를 복사해 오는 것뿐이다. 서버에 있는 원본은 전혀 건드리지 않는다.
명령어를 친다. 엔터를 누른다.
숫자가 올라간다. 10%... 20%... 30%...
'진짜 되고 있어.'
잠시 화장실에 다녀와보니 터미널을 본다. 완료됐다!
backend-api 폴더가 생겼다. 안으로 들어간다. 파일 목록을 본다. .git 폴더, .gitignore 파일, README.md, package.json, src 폴더, test 폴더...
'와... 진짜 회사 코드가 내 컴퓨터에 있다.'
가슴이 두근거린다.
나는 회사 코드를 처음 클론받았을 때 실수를 했다. 바탕화면에 클론을 받았다. 괜찮아 보였다. 문제없이 작동했다. 한 달 동안. 그러다가 2주차에 다른 저장소도 클론받았다. frontend-web, mobile-app, data-pipeline... 바탕화면이 폴더로 가득 찼다. 지저분했다.
3주차에는 실수로 backend-api 폴더를 휴지통에 버렸다. 그리고 그날 저녁에 급하게 코드를 고쳐야 하는 일이 생겼다. 휴지통을 뒤졌다. 다행히 있었다. 복원했다. 하지만 심장이 쿵쾅거렸다.
그날 선배가 말했다. "작업 디렉토리는 바탕화면에 모아두지 말고 폴더를 따로 만들어 보관하세요. 바탕화면은 임시 파일 두는 곳이에요." 그래서 지금은 모든 프로젝트를 앞서 말한 것처럼 나의 고유 아이디 폴더 아래에 workspace에 둔다. 깔끔하다. 백업도 쉽다. 실수로 지울 일도 없다.
클론을 받았다. 이제 어떤 브랜치에서 작업해야 할까?
현재 브랜치를 확인한다. main 브랜치에 있다. 모든 브랜치를 본다. main, develop, feature/user-api, hotfix/login-bug...
어떤 브랜치가 메인인지 알아야 한다. README를 다시 읽어본다. 브랜치 전략이 설명되어 있다. main은 운영 배포 브랜치라서 절대 직접 커밋하면 안 된다. develop이 개발 브랜치다. 여기서 작업한다.
아하. develop에서 작업하는구나.
브랜치를 바꾼다. develop 브랜치로 체크아웃한다. 좋다. 이제 develop 브랜치에 있다.
회사마다 다르지만, 일반적인 브랜치 전략은 비슷하다.
Git Flow가 가장 흔하다. main 브랜치는 운영 환경이고, develop 브랜치에서 개발한다. feature 브랜치에서 기능을 만들고, hotfix 브랜치에서 긴급 버그를 고친다.
GitHub Flow는 더 심플하다. main 브랜치 하나에서 운영과 개발을 모두 한다. 기능별로 브랜치를 만들어서 작업하고 바로 main에 merge한다.
회사마다 규칙이 있다. 대부분의 회사에서는 main에는 절대 직접 커밋하지 않는다. develop에서 브랜치를 만들어 작업한다. PR을 통해서만 merge한다.
첫 주에 분석만 해야 한다면 브랜치를 만들지 말고 develop에서 코드만 읽자. 브랜치를 잘못 만들거나, 잘못된 브랜치에서 작업하면 나중에 복구하기 번거롭다.
로그인 API에 validation을 추가하는 작업이었다.
README를 보니 "develop에서 브랜치를 만들어 작업하세요"라고 적혀 있었다.
나는 터미널을 열고 브랜치를 만들었다. 코드를 수정했다. 커밋했다. PR을 올렸다.
선배가 PR을 보고 댓글을 달았다.
"이 브랜치, main에서 만든 거 아닌가요?"
'엥? develop에서 만들었는데?'
확인해봤다. 로그를 봤다. 아... main에서 브랜치를 만들었다. develop가 아니라.
왜 그랬을까? 클론받고 나서 develop로 checkout을 안 했던 거다. 기본적으로 main에 있었는데, 나는 그걸 모르고 브랜치를 만들었다.
선배가 친절하게 설명해줬다.
"브랜치 만들기 전에 항상 확인하세요. git branch로요. 그리고 develop가 최신인지도 확인하세요. git pull로요."
그날 이후로 나는 브랜치 만들기 전에 항상 4단계를 거친다.
현재 브랜치 확인 -> develop로 이동 -> 최신 코드 받기 -> 브랜치 생성
이 4단계면 실수가 없다.
클론을 받으면 .gitignore 파일이 있다. 이건 "Git이 무시할 파일 목록"이다.
파일을 열어본다. node_modules, .env, build 폴더, 로그 파일, IDE 설정, OS 파일... 이런 것들이 적혀 있다.
만약 .gitignore가 없다면 어떻게 될까?
node_modules 폴더에 있는 수만 개 파일을 Git에 커밋하게 된다. .env 파일에 있는 DB 비밀번호를 실수로 push한다. 빌드 결과물을 저장소에 올린다.
즉, 저장소가 엉망이 되고, 보안 사고가 난다.
회사 .gitignore에 없는데 내 환경에서 생기는 파일들이 있다.
맥 사용자라면 .DS_Store 같은 파일이 생긴다. 윈도우는 Thumbs.db가 생긴다. IDE를 쓰면 .idea나 .vscode 폴더가 생긴다.
직접 추가하지 말고, 팀에 물어보자. "제가 .vscode 폴더를 .gitignore에 추가해도 될까요?"
이미 팀 컨벤션이 있을 수 있다. 혼자 추가하면 나중에 PR에서 충돌난다.
이제 진짜로 코드를 봐야 한다.
파일 목록을 본다. .git 폴더, .gitignore, README, package.json, src 폴더, test 폴더...
'어디부터 봐야 하지?'
README를 다시 읽는다. 프로젝트 구조가 설명되어 있다. routes 폴더에는 API 엔드포인트가 정의되어 있고, controllers에는 비즈니스 로직이, models에는 데이터베이스 모델이, services에는 외부 서비스 연동이, utils에는 유틸리티 함수가 있다.
routes 폴더의 index 파일을 열어본다. Express 라우터가 보인다. health 체크 엔드포인트, users 라우트, auth 라우트...
'오... 진짜 회사 코드다.'
학교 과제랑은 다르다. 체계적이다. 주석도 있고, 구조도 명확하다.
controllers 폴더의 users 파일을 열어본다. 사용자를 조회하는 함수다. try-catch로 에러 핸들링을 하고, 로깅도 하고, 상태 코드도 제대로 반환한다.
'에러 핸들링도 하고, 로깅도 하고... 배울 게 많겠다.'
파일을 하나씩 열어본다. 코드를 읽는다. 아직 다 이해는 안 되지만, 괜찮다. 천천히 배우면 된다.
workspace 디렉토리를 만들었는가? 저장소 주소를 확인했는가? SSH 방식을 선택했는가? git clone을 실행했는가? 클론이 완료됐는가?
현재 브랜치를 확인했는가? 전체 브랜치 목록을 봤는가? README에서 브랜치 전략을 파악했는가? develop 브랜치로 checkout 했는가?
.gitignore 파일을 확인했는가? .env.example이 있는지 봤는가? README를 읽었는가? 프로젝트 구조를 파악했는가?
필요한 런타임 버전을 확인했는가? 의존성 설치 방법을 알아봤는가? 로컬 실행 방법을 파악했는가?
터미널을 내려다본다. workspace/backend-api 폴더에 있다. develop 브랜치다.
회사 코드가 내 컴퓨터에 있다. 진짜로.
에디터를 연다. 좌측에 프로젝트 트리가 펼쳐진다. 수백 개의 파일이 보인다.
'이 코드들이... 지금 이 순간에도 수백만 명이 쓰는 서비스를 돌리고 있구나.'
슬랙에 팀장님이 메시지를 보낸다.
"클론 다 받으셨나요? 내일 오전 10시에 코드 투어 해드릴게요. 주요 모듈들 설명해드릴게요."
답장을 한다.
"네, 클론 완료했습니다. 감사합니다. 내일 뵙겠습니다!"
미소가 지어진다.
파일 탐색기를 천천히 스크롤한다. controllers, models, routes, services...
'내일이면... 이 코드들을 이해하게 되겠지?'
설렌다. 두렵기도 하지만, 더 설렌다.
마우스를 src 폴더 위에 올린다. 클릭한다. 하위 폴더들이 펼쳐진다. index 파일을 연다.
'이게... 시작점이구나.'
코드를 읽는다. 천천히, 한 줄 한 줄.
내일이면, 이 코드를 수정하게 될지도 모른다.
다음 주면, 내 코드가 이 파일 어딘가에 merge될지도 모른다.
몇 달 후면, 나도 이 코드를 설명할 수 있게 될지도 모른다.
'드디어... 진짜 개발자가 되어가고 있구나.'
노트북을 덮는다. 오늘은 여기까지.
내일부터는 진짜 시작이다.