โน๏ธ ํ๋ก์ ํธ ๊ฐ์ด๋
๐ 3/21 - 1์ผ์ฐจ ํ๊ณ (๋์ ์๋น์ค ํ์ ๋ฐ ํ๋ก์ ํธ ํ๊ฒฝ ์ธํ )
์ด์ ์์
์ด ๋๋ ํ ์คํ 8์ 30๋ถ ๊ธฐ์ฐจ๋ฅผ ํ๊ณ ์์ธ๋ก ์ฌ๋ผ์๋ค. ๊ณ ์์์ ๋์ฐฉํด ์ง์ ๋์ถฉ ํ๊ณ ๋๋ ์ด๋๋ง ๋ฐค 11์๊ฐ ํ์ฉ ์ง๋ ์์๋ค. ๊ธํ๊ฒ ๋์ ๋ถ์์ง๋ง, ๋ฏ์ ์ ์๋ฆฌ ๋๋ฌธ์ธ์ง ์๊พธ ๋ค์ฒ์ด๊ฒ ๋๋ค.
์ค๋์ ์๋ฆฌ์คLab์์ ํ์๋ถ๋ค์ ์ฒ์์ผ๋ก ์คํ๋ผ์ธ์์ ๋ง๋๋ ๋ ์ด์๋ค. ๋น๋ชฝ์ฌ๋ชฝ ์ผ์ด๋์ ์์ธ ๊ตฌ๊ฒฝ๋ ํ ๊ฒธ 30๋ถ ์ ๋ ๊ฑธ์ด์ ์๋ฆฌ์คLab์ผ๋ก ํฅํ๋ค.
Jenkins๋ CI/CD ์๋ํ๋ฅผ ์ํ ๋๊ตฌ์ด์ง๋ง, Windows ํ๊ฒฝ์์๋ Java ํ๊ฒฝ ์ค์ ๋ฐ ์ค์น ๊ณผ์ ์์ ๋ค์ํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ฌ ๋ก์ปฌ ์ค์น์ ์ด๋ ค์์ด ์์๋ค. ์ด์ Jenkins ๊ณต์ ์ด๋ฏธ์ง๋ฅผ ํ์ฉํด Docker๋ก Jenkins ์ปจํ
์ด๋๋ฅผ ์คํํ์๊ณ , GitHub ๋ ํฌ์งํ ๋ฆฌ์ ์ฐ๋ํ ๋ค, ํด๋น ๋ ํฌ ๋ด ํ์ผ์ ์คํํ๋ ๋ช
๋ น์ด๋ฅผ Jenkins Job์ ์
๋ ฅํด ๋น๋๋ฅผ ์ํํด๋ณด์๋ค. ๋ช
๋ น์ด๊ฐ ์ ์์ ์ผ๋ก ์คํ๋๋์ง ํ์ธํจ์ผ๋ก์จ Jenkins์ GitHub ๋ ํฌ์งํ ๋ฆฌ ๊ฐ ์ฐ๊ฒฐ์ด ์ ์ด๋ฃจ์ด์ก๋์ง๋ฅผ ๊ฒ์ฆํ ์ ์์๋ค.
๐ฅ Jenkins ์ค์ ๋ฐ GitHub Repo์์ ์ฐ๊ฒฐ
[ Jenkins์ ์ฐ๊ฒฐํ GitHub ๋ ํฌ ์์ฑ ]
https://github.com/kys0529/Jenkins_prac
[ ์๋ก์ด Jenkins ์ปจํ ์ด๋ ์คํ (in cmd) ]
docker run -d -p {์ธ๋ถ ํฌํธ}:{์ปจํ ์ด๋ ๋ด๋ถ ํฌํธ} -p 50000:50000 --name {์ปจํ ์ด๋ ์ด๋ฆ} jenkins/jenkins
> Jenkins ๊ณต์ ์ด๋ฏธ์ง๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋ก์ด ์ปจํ ์ด๋๋ฅผ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์คํ
> ํฌํธ 8080(์น UI)๊ณผ 50000(์์ด์ ํธ ํต์ ์ฉ)์ ์คํ
[ ์ปจํ ์ด๋ ์คํ ์ฌ๋ถ ํ์ธ (in cmd) ]
docker ps
> ํ์ฌ ์คํ ์ค์ธ Docker ์ปจํ ์ด๋ ๋ชฉ๋ก์ ํ์ธํ์ฌ Jenkins๊ฐ ์ ๋ ์๋์ง ์ฒดํฌ
[ Jenkins ์ด๊ธฐ ๋น๋ฐ๋ฒํธ ํ์ธ (in cmd) ]
docker exec -it {์ปจํ ์ด๋ ์ด๋ฆ} cat /var/jenkins_home/secrets/initialAdminPassword
> Jenkins ์ด๊ธฐ ์ค์น ์ ํ์ํ ๊ด๋ฆฌ์ ๋น๋ฐ๋ฒํธ๋ฅผ ์ถ๋ ฅ
[ Jenkins ์น UI ์ ์ ๋ฐ ์ด๊ธฐ ๋น๋ฐ๋ฒํธ ์ ๋ ฅ ]
http://localhost:8080
> ๋ธ๋ผ์ฐ์ ์์ http://localhost:8080 ์ ์ ํ, ์์์ ํ์ธํ ์ด๊ธฐ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅํ์ฌ ์ด๊ธฐ ์ค์ ์ ์งํ
[ Freestyle Job ์์ฑ ๋ฐ GitHub Webhook ์ฐ๊ฒฐ]
Jenkins์์ New Item > Freestyle Project๋ฅผ ์ ํํ์ฌ ์๋ก์ด Job ์์ฑ
http://{๊ณต์ธ IP}:8080/github-webhook/
> GitHub์์ Webhook ์ค์ ์ Payload URL์ ์ ๊ฐ์ด ์ ๋ ฅ
> ํด๋น Webhook์ GitHub์์ push ์ด๋ฒคํธ ๋ฐ์ ์ Jenkins Job์ ํธ๋ฆฌ๊ฑฐํ๋ ์ญํ
[ Jenkins ์ปจํ ์ด๋ ๋ด Python ์ค์น ์ฌ๋ถ ํ์ธ (in cmd) ]
docker exec -it {์ปจํ ์ด๋ ์ด๋ฆ} bash
> Jenkins ์ปจํ ์ด๋ ๋ด๋ถ๋ก ์ง์
python3 --version
> Python์ด ์ค์น๋์ด ์๋์ง ํ์ธ
[ Docker ์ปจํ ์ด๋ ๋ด๋ถ์ python3 ์ค์น ]
docker exec -it --user root {์ปจํ ์ด๋ ์ด๋ฆ} bash
> ๋ฃจํธ ๊ถํ์ผ๋ก ์ปจํ ์ด๋์ ์ง์
apt update
apt install -y python3 python3-pip
> Python3 ๋ฐ pip ์ค์น
[ Build Steps ์ค์ ]
Jenkins Job ์ค์ > Build Steps ํญ๋ชฉ์์ "Execute shell" ์ ํ
python3 hello.py
> ๋ ํฌ ๋ด hello.py ํ์ผ์ ์คํํ์ฌ Jenkins์ GitHub ๋ ํฌ ๊ฐ์ ์ฐ๊ฒฐ ๋ฐ ์คํ ์ฌ๋ถ๋ฅผ ํ์ธ
๊ทธ ํ ํ๋ช
๊ณผ ํ์ฅ์ ์ ํ๋ค. ํ๋ช
์ GPT์ ๋์์ ๋ฐ์ ๊ฒฐ์ ํ๊ณ , ํ์ฅ์ ์๋ฌด๋ ํ๋ ค๊ณ ํ์ง ์์์ ๋ด๊ฐ ๋งก๊ฒ ๋๋ค. ๋์์ ๋ฆฌ๋ ์ญํ ์ ํ์ง๋ ์์ง๋ง, ํญ์ ๊ทธ๋ ๋ฏ ํ ์ฌ๋์ด ์์ผ๋ฉด ๊ฒฐ๊ตญ ๋ด๊ฐ ํ๊ฒ ๋๋ ํธ์ด๋ค.
ํ์ฅ์ ์ ํ ํ์๋ ๋์ ์๋น์ค์ Figma, ERD, ๊ธฐํ์ ๊ฐ์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํด์ ๊ธฐ๋ฅ๋ค์ ๋๋ต์ ์ผ๋ก ํ์
ํ๋ค. ๊ทธ๋ฆฌ๊ณ ํ์๋ค๊ณผ ํจ๊ป ์๋น์ค๋ฅผ ์ง์ ์ฌ์ฉํด๋ณด๋ฉด์ ํ์์ ํ
์คํธ์ ํฌ๋ก์ค ํ
์คํธ๋ฅผ ์งํํ๋ค. ์ด๋ค ๊ธฐ๋ฅ๋ค์ด ๊ตฌํ๋ผ ์๋์ง, ์์ง ๊ตฌํ๋์ง ์์ ๊ฑด ๋ฌด์์ธ์ง, ์ด๋ค ์ค๋ฅ๋ค์ด ์๋์ง๋ฅผ ํ๋ํ๋ ์ง์ ํ์ธํด๋ณด๋ฉด์ ์ ๋ฐ์ ์ธ ํ๋ฆ์ ์ดํดํ๋ค.
๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ์ผ๋ก ๊ตฌ๊ธ ์คํ๋ ๋์ํธ์ ๊ธฐ๋ฅ ๋ช
์ธ์๋ฅผ ์ ๋ฆฌํ๊ณ , ๊ฐ์ ํ๋์ฉ ๊ธฐ๋ฅ์ ์ ์ ํด์ TC ์ด์๋ ์์ฑํ๋ค. ์ํต์ ๋ ์ํํ๊ฒ ํ๊ธฐ ์ํด, Figma์ ์์ฃผ ์ฐ๋ URL์ด๋ ํ๋ก์ ํธ ์ฐ์ถ๋ฌผ, ๊ทธ๋ฆฌ๊ณ ์งํ ์ํฉ ๋ฑ์ ํ๋์ ๋ณผ ์ ์๊ฒ ์ ๋ฆฌํด๋์๋ค.
GitHub๋ GitHub Desktop์ ํ์ฉํ๋ฉด GUI๋ก ์ฝ๊ฒ ์กฐ์ํ ์ ์์ด์ Git ๊ฒฝํ์ด ์์ด๋ ๋๊ตฌ๋ ์ด๋ ต์ง ์๊ฒ ์ฌ์ฉํ ์ ์์๋๋ฐ, GitLab์ ์ฐ๋ฆฌ ๋ชจ๋ ์ฒ์์ด๋ผ CLI ์กฐ์์ ๋ง์ด ํค๋งธ๋ค. ๊ทธ๋๋ SSH Key๋ฅผ ๋ฐ๊ธ๋ฐ๊ณ , Clone๊ณผ Pull๊น์ง๋ ๊ฒฐ๊ตญ ๋ค ์ฑ๊ณตํ๋ค. ์ค๋์ ์ผ๋จ ํ๋ก์ ํธ์ ์ด๊ธฐ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ง ๋ง๋ค์ด๋ ์ํ๋ค.
์คํ 8์์๋ ์คํผ์ค ์์๊ฐ ์งํ๋๋ค. ์ด ์๊ฐ์ QA ์ค๋ฌด ๋ฐ ์๋ํ ๊ฒฝํ์ด ์๋ ํ์คํ ํ์
์๋ถ๊ป 1์๊ฐ ๋์ ๊ถ๊ธํ ์ ์ ๋ฌผ์ด๋ณผ ์ ์๋ ์ ๋ง ์์คํ ์๊ฐ์ด๋ค. ์ฌ์ค ํ๋ก์ ํธ ์ฒซ๋ ์ด๋ผ ์ด๊ฒ์ ๊ฒ ์ ์ ์ด ๋๋ฌด ์์๊ณ , ์ง๋ฌธ ๋ฆฌ์คํธ๋ฅผ ๋ฏธ๋ฆฌ ์ค๋นํ์ง ๋ชปํ ๊ฒ ๋๋ฌด ์์ฌ์ ๋ค. ๋ค์๋ถํฐ๋ ๊ผญ ๋ฏธ๋ฆฌ ์ง๋ฌธ์ ์ ๋ฆฌํด์ ์ด ์๊ฐ์ ๋ ์ ์ฉํ๊ฒ ํ์ฉํด์ผ๊ฒ ๋ค.
๐ฅ SSH Key ์ค์ ๋ฐ GitLab ํ๋ก์ ํธ Clone
[ SSH Key ์์ฑ (in cmd) ]
ssh-keygen -t rsa -b 4096 -C "{GitLab์ ๋ฑ๋ก๋ ์ด๋ฉ์ผ}"
> ์ ๋ช ๋ น์ด ์ ๋ ฅ ํ Enter 3๋ฒ ์ ๋ ฅ
> SSH ํค๊ฐ ์์ฑ๋๋ฉด ํค ํ์ผ ์ ์ฅ ์์น๊ฐ ์ถ๋ ฅ
[ SSH ํค ๋ณต์ฌ ]
ํ์ผ ํ์๊ธฐ๋ก ์์ฑ๋ SSH ํค ์์น๋ก ์ด๋ (๋ณธ์ธ์ C:\Users\samsung\.ssh)
๋น๋ฐ ํค(id_rsa)๊ฐ ์๋ ๊ณต๊ฐ ํค(id_rsa.pub) ์ฌ์ฉ (๊ณต๊ฐ ํค ๋ด์ฉ ssh-rsa ~~~~ ํํ๋ก ์์)
๊ณต๊ฐ ํค ๋ด์ฉ ๋ณต์ฌ
[ GitLab์์ SSH Key ๋ฑ๋ก ]
GitLab ์ ์ ํ ํ๋กํ ์ค์ ์ผ๋ก ์ด๋
์ข์ธก ๋ฉ๋ด์์ SSH Keys ํด๋ฆญ ํ, ๋ณต์ฌํ SSH ๊ณต๊ฐ ํค๋ฅผ Key ์ ๋ ฅ๋์ ๋ถ์ฌ๋ฃ๊ธฐ
[ ํด๋ ์์ฑ ๋ฐ ํด๋ก ]
์ํ๋ ์์น์ ํ๋ก์ ํธ ํด๋ ์์ฑ ํ, VS Code์์ ํด๋น ํด๋ ์ด๊ธฐ
git clone {GitLab SSH ํค}
๐ฅ Git ๋ช
๋ น์ด
[ Clone ๋ช
๋ น์ด ]
git clone {Gitlab์์ ๋ณต์ฌํ SSH}
[ Repo๋ฅผ Cloneํ ํด๋๋ก ์ด๋ ]
cd {ํด๋ ์ด๋ฆ}
[ branch ์์ฑ ๋ฐ ํด๋น branch๋ก ์ด๋ ]
git checkout -b {branch ์ด๋ฆ}
[ ํ์ฌ branch ํ์ธ (*์ด ํ์ฌ ์์นํ branch) ]
git branch
[ Pull ๋ช
๋ น์ด ]
git pull origin {branch ์ด๋ฆ}
[ Push ๊ณผ์ ]
๋ณ๊ฒฝ ์ฌํญ ํ์ธ: git status
๋ณ๊ฒฝ๋ ํ์ผ ์คํ
์ด์ง: git add .
์ปค๋ฐ ๋ง๋ค๊ธฐ: git commit -m "์ปค๋ฐ ๋ฉ์์ง"
Push: git push origin {branch ์ด๋ฆ}
๐ 3/22 - ๊ฐ์ธ ๊ณต๋ถ (Sourcetree)
์ฌ์ค ์ฃผ๋ง์ ์๋ฌต์ ์ผ๋ก ํ๋ก์ ํธ๋ฅผ ์งํํ์ง ์๊ธฐ๋ก ํ์์ง๋ง, ๋๊ธฐ ์น๊ตฌ๊ฐ SW ๋ง์์คํธ๋ก ๋ฉด์ ๋๋ฌธ์ ์์ธ์ ์ฌ๋ผ์จ ๊น์ ์ผ๊ตด๋ ๋ณผ ๊ฒธ ์ฑ์์์ ๋ฐฅ์ ๋จน๊ณ , ์นดํ์ ๋ค๋ฌ ์ ๊น ํ๋ก์ ํธ ๊ด๋ จ ๊ณต๋ถ๋ฅผ ๊ฐ์ธ์ ์ผ๋ก ์งํํ๋ค.
๋ง์นจ ๊ทธ ์น๊ตฌ๊ฐ Docker๋ฅผ ๋ค๋ค๋ณธ ์ ์ด ์์ด์, ์ด์ ๋ด๊ฐ Docker๋ก ์งํํ๋ "Jenkins ์ค์ ๋ฐ GitHub Repo์์ ์ฐ๊ฒฐ" ๊ณผ์ ์ ์ค๋ช
ํด์คฌ๋๋, ์น๊ตฌ๊ฐ ์ด๋ฐ ๋ง์ ํด์คฌ๋ค. “๋๊ฐ ์ง๊ธ์ฒ๋ผ ๋ช
๋ น์ด ํ๋ํ๋ ์ณ์ Jenkins ์ปจํ
์ด๋ ๋์ฐ๊ณ ์ค์ ํ๋ ์ด๋ฐ ์์
๋ค์ Dockerfile์ด๋ Docker Compose๋ก ์ ๋ฆฌํด๋๋ฉด, ํ ์ค ๋ช
๋ น์ด๋ก ํตํฉ ์คํํ ์ ์์ด” ์ฆ, Dockerfile์ ๋ง๋ค์ด์ Jenkins์ Python๊น์ง ๋ฏธ๋ฆฌ ์ค์นํด๋๋ฉด, docker build ํ ๋ฒ์ผ๋ก Jenkins + Python3 ํ๊ฒฝ์ด ๊ตฌ์ฑ๋ ์ด๋ฏธ์ง๋ฅผ ๋ฐ๋ก ์์ฑํ ์ ์๋ค๋ ๋ป์ด์๋ค. ๋ฌผ๋ก ์ฝ์น๋๊ป์ ์ฒ์๋ถํฐ Dockerfile๋ก ์ฃผ์
จ๋ค๋ฉด ๊ธ๋ฐฉ ๋๋ฌ๊ฒ ์ง๋ง, ์ด ์ค์ต์ ๋ชฉ์ ์์ฒด๊ฐ ์ง์ Jenkins๋ฅผ ์ธํ
ํด๋ณด๋ ๋ฐ ์์ผ๋๊น! ๊ทธ๋๋ Docker๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ํ๋ ๋ฐฐ์๊ฐ ์
์ด๋ค.
๊ทธ๋ฆฌ๊ณ ๋ง๋ถ์ฌ, GitLab ์ด์ผ๊ธฐ๋ฅผ ํ๋ค๊ฐ GitLab์๋ GitHub Desktop์ฒ๋ผ GUI ํด๋ผ์ด์ธํธ๊ฐ ์์ด์, CLI์ ์ต์ํ์ง ์์ ๋์ ํ์๋ค์ด ๊ฝค๋ ํ๋ค์ดํ๊ณ ์๋ค๊ณ ํ์์ฐํ๋๋ ์น๊ตฌ๊ฐ "Sourcetree"๋ฅผ ์ถ์ฒํด์คฌ๋ค.
๐ฅ Sourcetree ์ฌ์ฉ ๋ฐฉ๋ฒ
[ Access Token ๋ฐ๊ธ ๋ฐฉ๋ฒ - GitHub ]
Settings > Developer Settings
Personal access token > Tokens (classic) > Generate new token (classic)
[ Access Token ๋ฐ๊ธ ๋ฐฉ๋ฒ - GitLab ]
User Settings > Access tokens > Add new token
[ Access Token ๋ฐ๊ธ ๋ฐฉ๋ฒ - GitLab EE ]
User Settings > Access Tokens
[ ํธ์คํ ๊ณ์ ์ฐ๋ ]
(1) Host
New tab > Remote > ๊ณ์ ์ถ๊ฐ > ํธ์คํ ์๋น์ค ๋ฐ ์ ํธ ํ๋กํ ์ฝ ์ ํ
GitLab EE๋ ํธ์คํธ URL ์ถ๊ฐ์ ์ผ๋ก ์ ๋ ฅ (ex: https://kdt-gitlab.elice.io/)
(2) Credentials
์ธ์ฆ์ Personal Access Token ์ ํ
Personal Access Token ์๋ก๊ณ ์นจ ๋ฒํผ ํด๋ฆญ > ๋ณธ์ธ ์ฌ์ฉ์ ์ด๋ฆ ์ ๋ ฅ ๋ฐ ์ํธ์ ๋ฐ๊ธ๋ฐ์ Access Token ์ ๋ ฅ
๐ 3/23 - ๊ฐ์ธ ๊ณต๋ถ (Docker ๋ฐ Jenkins)
์ค๋์ ํ ํ๋ก์ ํธ๋ฅผ ํจ๊ป ์งํ ์ค์ธ ํ์๋ถ๊ณผ ์๋ด์ญ ์นดํ์์ ๋ง๋, Python์ ๊ธฐ๋ณธ ๋ฌธ๋ฒ๋ถํฐ Selenium, pytest, ๊ทธ๋ฆฌ๊ณ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ์ ๋ํด ์ค๋ช
ํด๋๋ ธ๋ค. ์ค๋ช
์ ํ๋ฉด์ ๋ ์ญ์ ๊ธฐ๋ณธ ๊ฐ๋
๋ค์ ๋ค์ ๋ ์ฌ๋ฆด ์ ์์ด ์ ์ตํ ์๊ฐ์ด์๋ค. ๊ทธ๋ฆฌ๊ณ ์ค๋ ์๋กญ๊ฒ ์๊ฒ ๋ ์ฌ์ค ํ๋! conftest.py ํ์ผ์ pytest๊ฐ ์๋์ผ๋ก ์ธ์ํด fixture๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๊ธฐ ๋๋ฌธ์, ๋ค๋ฅธ ๋ชจ๋์ฒ๋ผ importํ ํ์๊ฐ ์๋ค. ๋ค๋ง ์ด ํ์ผ์ ํ
์คํธ ํ์ผ๊ณผ ๊ฐ์ ๋๋ ํ ๋ฆฌ ๋๋ ์์ ๋๋ ํ ๋ฆฌ์ ์์ด์ผ ์๋ ์ธ์๋๋ฉฐ, ํ์ ๋๋ ํ ๋ฆฌ์ ์๋ conftest.py๋ ์๋์ผ๋ก ์ฝํ์ง ์๋๋ค.
Docker
• Dockerfile
~> ๋๋ง์ Docker Image๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์กฐ๋ฆฌ๋ฒ(๋ ์ํผ)
~> ์ด๋ค OS๋ฅผ ๊ธฐ๋ฐ์ผ๋ก, ์ด๋ค ํจํค์ง๋ฅผ ์ค์นํ ์ง, ์ด๋ค ์ค์ ์ ์ ์ฉํ ์ง ํ ์ค์ฉ ์์ฑํ๋ ์คํฌ๋ฆฝํธ
~> ์ฝ๊ฒ ๋งํด "๋ด๊ฐ ์ํ๋ ๊ฐ๋ฐ ํ๊ฒฝ์ ๊ทธ๋๋ก ์ด๋ฏธ์ง๋ก ๋ง๋ค ์ ์๋ ์ค๊ณ๋"
• Docker Image
~> ์ผ์ข
์ ์ค์น CD๋ ํ๋ก๊ทธ๋จ์ ์์ ํ ํ
ํ๋ฆฟ
~> ์ ํ๋ฆฌ์ผ์ด์
, ์ค์ , ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฑ ์คํ์ ํ์ํ ๋ชจ๋ ์์๊ฐ ํฌํจ๋ ๋ถ๋ณํ ์ํ์ ํจํค์ง
• Docker Container
~> ์ด๋ฏธ์ง๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์คํ ์ค์ธ ์ธ์คํด์ค
~> ์ฝ๊ฒ ๋งํ๋ฉด, ์ด๋ฏธ์ง๋ฅผ ์คํํด์ ๋ง๋ค์ด๋ธ ๋
๋ฆฝ์ ์ธ ์ด์ ํ๊ฒฝ
~> ์ฌ๋ฌ ๊ฐ์ ์ปจํ
์ด๋๋ฅผ ๊ฐ์ ์ด๋ฏธ์ง๋ก๋ถํฐ ์์ฑ ๊ฐ๋ฅ
• docker-compose.yml
~> ์ฌ๋ฌ ๊ฐ์ Docker ์ปจํ
์ด๋๋ฅผ ํ ๋ฒ์ ์คํ์ํค๋ ์คํ ๋งค๋์
~> ์ด๋ค ์ด๋ฏธ์ง๋ฅผ ์คํํ ์ง, ํฌํธ๋ฅผ ์ด๋ป๊ฒ ์ฐ๊ฒฐํ ์ง, ๋ณผ๋ฅจ์ ์ด๋์ ๋ง์ดํธํ ์ง ๋ฑ์ ์ ์
~> ์ฝ๊ฒ ๋งํ๋ฉด "Docker ํ๊ฒฝ ์ ์ฒด๋ฅผ ์๋์ผ๋ก ์ธํ
ํด์ฃผ๋ ์๋๋ฆฌ์ค ํ์ผ"
GitHub Webhook์ ์ค์ ํ ๋ ๊ณต์ธ IP๋ฅผ ์ด์ฉํด ์๋์ ๊ฐ์ด ์ค์ ํ์ง๋ง, ์ ์์ ์ผ๋ก ์ฐ๊ฒฐ๋์ง ์์๋ค๋ ์ฌ์ค์ ๋ค๋ฆ๊ฒ ์๊ฒ ๋์๋ค.
- GitHub Webhook: http://{๊ณต์ธ IP}:8080/github-webhook/
์ฆ, 21์ผ์ ์งํํ๋ Jenkins ์ค์ต ๋น์์๋ Job์ Build Steps์ python3 hello.py๋ฅผ ์
๋ ฅํ ๋ค Jenkins์์ ์๋์ผ๋ก Build Now ๋ฒํผ์ ๋๋ฌ ์คํํ๊ธฐ ๋๋ฌธ์, Jenkins์ GitHub ๊ฐ ์ฐ๋์ด ์ ์์ ์ผ๋ก ์๋ํ๋ ์ค๋ก๋ง ์๊ณ ์์๋ค. ํ์ง๋ง ์ค์ ๋ก๋ Webhook์ด ์ ๋๋ก ์ฐ๊ฒฐ๋์ง ์์๊ธฐ ๋๋ฌธ์, ์ดํ GitHub์์ push ์ด๋ฒคํธ๊ฐ ๋ฐ์ํด๋ Jenkins๊ฐ ์๋์ผ๋ก ๋น๋๋์ง ์๋ ์ํ์๋ค. ์ด ์ฌ์ค์ ์ค๋ GitHub ๋ ํฌ ๋ด์ hello.py ํ์ผ์ ์์ ํ๋ฉด์ ์๊ฒ ๋์๋ค.
GitHub Webhook ์ค์ ์ ๊ณต์ธ IP๋ฅผ ์ฌ์ฉํ์์๋ ์๋ ๋น๋๊ฐ ์๋ํ์ง ์์๋ ์ด์ ๋, ์ธ๋ถ์์ ํด๋น ํฌํธ(8080)๋ก ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํ ํ๊ฒฝ์ด์๊ธฐ ๋๋ฌธ์ด๋ค. ์ด๋ฌํ ๋ฌธ์ ๋ ๊ณต์ ๊ธฐ ํฌํธํฌ์๋ฉ ๋ฏธ์ค์ , ๋ก์ปฌ ๋ฐฉํ๋ฒฝ ์ฐจ๋จ, ๋๋ ISP์ ํฌํธ ์ ํ ๋ฑ ์ฌ๋ฌ ๊ฐ์ง ์์ธ์ผ๋ก ๋ฐ์ํ ์ ์๋ค.
ํ์ง๋ง ์ด ๋ชจ๋ ์ค์ ์ ํ๋ํ๋ ํ์ธํ๊ณ ๊ตฌ์ฑํ๋ ๊ณผ์ ์ด ๋ณต์กํ๊ณ ๋ฒ๊ฑฐ๋กญ๊ธฐ ๋๋ฌธ์, GPT์ ์ถ์ฒ๋๋ก ngrok์ ํ์ฉํด Jenkins๋ฅผ ์ธ๋ถ์ ์์ ํ๊ฒ ๋
ธ์ถ์ํค๋ ๋ฐฉ๋ฒ์ผ๋ก ์ ํํด๋ณด๊ธฐ๋ก ํ๋ค.
๊ณต์ธ IP
~> ํ์ฌ ๋ด ๊ณต์ธ IP ํ์ธ ์ฌ์ดํธ
~> ๊ณต์ธ IP๋ ์ธํฐ๋ท์์์ ๊ณ ์ ํ๊ฒ ์๋ณ๋๋ IP ์ฃผ์๋ก, ์ธ๋ถ์์ ์ ๊ทผ ๊ฐ๋ฅํ ์ฃผ์
~> ๋ณดํต ๊ฐ์ ์ด๋ ํ์ฌ์์๋ ํ๋์ ๊ณต์ธ IP๋ฅผ ๊ณต์ ๊ธฐ(๋ผ์ฐํฐ)๊ฐ ๊ฐ์ง๊ณ ์๊ณ , ๊ทธ ์๋์ ์ฌ๋ฌ ๋์ ์ปดํจํฐ๋ค์ด ์ฌ์ค IP๋ฅผ ํตํด ์ฐ๊ฒฐ
~> Jenkins๊ฐ ๋ก์ปฌ PC์ ์ค์น๋์ด ์๊ณ , ์ธ๋ถ(GitHub/GitLab)์์๋ ๊ณต์ธ IP๋ก ์ ์์ ์๋ํ๋๋ผ๋ ๋ค์๊ณผ ๊ฐ์ ์ด์ ๋ก ์คํจ ๊ฐ๋ฅ
• ๊ณต์ ๊ธฐ์์ ํฌํธํฌ์๋ฉ ์ค์ ์ด ์ ๋์ด ์์
• ๋ก์ปฌ ๋ฐฉํ๋ฒฝ์์ 8080 ํฌํธ๋ฅผ ์ฐจ๋จ ์ค
• ์ธํฐ๋ท ์ ๊ณต์
์ฒด(ISP)์์ ํฌํธ ์ฐจ๋จ ์ ์ฑ
์ด ์์
ngrok
~> ๋ก์ปฌ์์ ์คํ ์ค์ธ ์น ์ ํ๋ฆฌ์ผ์ด์
(์: Jenkins)์ ์ธ๋ถ์์ ์ ์ ๊ฐ๋ฅํ๋๋ก ๋ง๋ค์ด์ฃผ๋ ๋๊ตฌ
~> ์ฆ, ngrok์ด ์ ๊ณตํ๋ ์์ ํผ๋ธ๋ฆญ ์ฃผ์๋ฅผ ํตํด ๊ณต์ธ IP ์์ด๋ ์ธ๋ถ์์ ๋ด Jenkins์ ์ ๊ทผ ๊ฐ๋ฅ
~> ngrok์ ์ค์๊ฐ ํฐ๋๋ง ์ค๊ณ ํ๋ก๊ทธ๋จ์ด๋ฏ๋ก, ngrok์ด ์คํ ์ค์ธ ๋์์๋ง ์์ฑ๋ Forwarding ์ฃผ์๊ฐ ์ ํจ
๐ฅ ngrok ์ค์น ๋ฐฉ๋ฒ
[ ๊ณต์ ์ฌ์ดํธ์์ ๋ค์ด๋ก๋ ๋ฐ ์์ถ ํ๊ธฐ ]
https://ngrok.com/downloads/windows?tab=download
[ ngrok ํ์๊ฐ์ ๋ฐ ์ธ์ฆ ํ ํฐ ๋ฐ๊ธ ]
Identity & Access > Authtokens > Add Tunnel Authtoken
[ ์ธ์ฆ ํ ํฐ ๋ฑ๋ก (in ngrok.exe) ]
ngrok config add-authtoken {๋ฐ๊ธ ๋ฐ์ ํ ํฐ}
[ Jenkins์ฉ ํฌํธ 8080 ํฐ๋๋ง ์คํ (in ngrok.exe) ]
ngrok http 8080

> ngrok์ด ์์ฑํ Forwarding ์ฃผ์ ์์
Jenkins
๐ฅ GitLab ์ ์ฅ์ ์ฐ๊ฒฐ์ ์ํด ํ์ํ ํ๋ฌ๊ทธ์ธ
[ Docker ์ปจํ ์ด๋ ๋ด๋ถ์ ํ๋ฌ๊ทธ์ธ ์ค์น (in cmd) ]
docker exec -it {์ปจํ ์ด๋ ์ด๋ฆ} bash
> Jenkins ์ปจํ ์ด๋ ๋ด๋ถ๋ก ์ง์
jenkins-plugin-cli --plugins git:5.7.0
> Git SCM ์ง์: Jenkins๊ฐ Git ์ ์ฅ์์์ ์ฝ๋๋ฅผ ํด๋ก ํ๊ณ ๊ฐ์ ธ์ฌ ์ ์๊ฒ ํด์ค
jenkins-plugin-cli --plugins gitlab-plugin:1.9.7
> GitLab ์ฐ๋: GitLab Webhook, GitLab credentials, GitLab SCM UI ์ฐ๋ ๋ฑ์ ๋ด๋น
ํด๋น ์ปจํ
์ด๋ Stop & Start
> Jenkins ํ๋ฌ๊ทธ์ธ์ ์ค์น ํ ๋ฐ๋์ ์ฌ์์ํด์ผ ์ ์ฉ
๐ฅ ์ปจํ ์ด๋ ๋ด๋ถ์ Python3, ๊ฐ์ ํ๊ฒฝ, Chrome ์ค์น
[ ๋ฃจํธ ๊ถํ์ผ๋ก Docker ์ปจํ ์ด๋ ๋ด๋ถ ์ง์ (in cmd) ]
docker exec -it --user root {์ปจํ ์ด๋ ์ด๋ฆ} bash
> ๋ฃจํธ ๊ถํ์ผ๋ก ์ปจํ ์ด๋์ ์ง์
[ Python3 ์ค์น (in cmd) ]
apt update
apt install -y python3 python3-pip
> Python3 ๋ฐ pip ์ค์น
[ ๊ฐ์ ํ๊ฒฝ ์ค์น (in cmd) ]
apt-get update
apt-get install -y python3-venv
> ํ์ ํจํค์ง ๋ฐ ๊ฐ์ ํ๊ฒฝ ์ค์น
[ Chrome ์ค์น (in cmd) ]
apt-get update
apt-get install -y wget gnupg2 curl unzip
> ํ์ ํจํค์ง ์ค์น
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
apt-get install -y ./google-chrome-stable_current_amd64.deb
> Chrome ์ค์น
๐ฅ headless ์ต์ ์ถ๊ฐ
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
@pytest.fixture
def createDriver():
chromeOption = Options()
chromeOption.add_argument('--start-maximized') # ์ ์ฒด ํ๋ฉด
chromeOption.add_argument('--incognito') # ์ํฌ๋ฆฟ ๋ชจ๋
chromeOption.add_argument("--headless") # GUI ์์ด ํ
์คํธ
chromeOption.add_argument("--no-sandbox") # ๋ธ๋ผ์ฐ์ ์ ๋ณด์ ๊ธฐ๋ฅ ์์ด ํ
์คํธ
chromeOption.add_argument('--disable-dev-shm-usage') # shared memory ๋ฌธ์ ๋ฐฉ์ง
chromeOption.add_argument('--disable-gpu') # ๊ฐ์ํ๊ฒฝ์์ GPU ๊ธฐ๋ฅ ๋นํ์ฑํ
driver = webdriver.Chrome(options=chromeOption)
yield driver
driver.quit()
.๐ฅ ์์กด์ฑ ํ์ผ(requirements.txt) ์ถ๊ฐ
pytest
selenium
๐ฅ Jenkinsfile ์ถ๊ฐ
pipeline {
agent any
stages {
stage('Run Tests') {
steps {
sh '''
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
python3 -m pytest
'''
}
}
}
}
๐ฅ GitLab๊ณผ Jenkins ์ฐ๋ ๋ฐฉ๋ฒ
[Jenkins] Jenkins GitLab ํ๋ก์ ํธ ์ฐ๋ํ๊ธฐ 01
[Jenkins] Jenkins GitLab ํ๋ก์ ํธ ์ฐ๋ํ๊ธฐ 01Jenkins์์ GitLab, GitHub๊ณผ ๊ฐ์ Git Repository์ ์ฐ๋ํ์ฌ ํ๋ก์ ํธ๋ฅผ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.๊ทธ์ค GitLab ํ๋ก์ ํธ์ ์ฐ๋ํ๊ธฐ ์ํด์๋ ์ด๋ค ์ค์ ์ด ํ์ํ์ง ์
every-up.tistory.com
[Jenkins] Jenkins GitLab ํ๋ก์ ํธ ์ฐ๋ํ๊ธฐ 02
[Jenkins] Jenkins GitLab ํ๋ก์ ํธ ์ฐ๋ํ๊ธฐ 02Project Access Tokens ๋ฐ๊ธ ํ ํด๋น Tokens์ผ๋ก GitLab ์๋ฒ๋ฅผ ์ถ๊ฐํ๋ ์์ ์ ์๋ฃํ์๊ณ ,์ด์ GitLab ํ๋ก์ ํธ ์ฐ๋๊ณผ ๊ฐ๋จํ Pipeline์ ๋์ํ๋ ์ค์ ์ ์งํํด๋ณด
every-up.tistory.com
[Jenkins] Jenkins GitLab ํ๋ก์ ํธ ์ฐ๋ํ๊ธฐ 03
[Jenkins] Jenkins GitLab ํ๋ก์ ํธ ์ฐ๋ํ๊ธฐ 03GitLab ํ๋ก์ ํธ ์ฐ๋๊ณผ ๊ฐ๋จํ Pipeline์ ๋์ํ๋ ์ค์ ์ ์๋ฃํ์๊ณ ,์ด์ WebHook์ ์ฐ๋ํ์ฌ Commit ๋ฑ์ Event ์ ์๋์ผ๋ก Jenkins Pipeline์ด ๋์๋๋๋ก ์ค์
every-up.tistory.com
> Webhook URL์์ http://localhost:8080 ๋ถ๋ถ์ ngrok์ด ์์ฑํ Forwarding ์ฃผ์๋ก ๋ณํ
๐ 3/24 - 2์ผ์ฐจ ํ๊ณ (๋์ ์๋น์ค ๊ธฐ๋ฅ ๋ช ์ธ์๋ฅผ ๋ฐํ์ผ๋ก TC ์์ฑ)
์ค๋์ ๋ณธ๊ฒฉ์ ์ธ ์์
์ ์์ ๊ฐ๋จํ ์คํฌ๋ผ ํ์๋ฅผ ์งํํ๋ค. ํ์๋ณ๋ก ์์ฑํ ํ
์คํธ ์ผ์ด์ค๋ฅผ ํจ๊ป ๊ฒํ ํ๊ณ ํผ๋๋ฐฑ์ ์ฃผ๊ณ ๋ฐ์์ผ๋ฉฐ, AI ๊ธฐ๋ฐ ๊ธฐ๋ฅ(์ทจํฉ๋ฅ , DB ์ ์ฅ์ ๋ฑ)์ ๊ตฌ์กฐ ๋ฐ ์ฒ๋ฆฌ ๋ฐฉ์์ ๋ํด ๋
ผ์ํ๋ค. ์ด์ด ์ฌ์ดํธ ์ ๋ฐ์ ๋ถ์ํ๋ฉฐ ์ฃ์ง ์ผ์ด์ค์ ๋๋ฝ๋ ์ค๋ฅ๋ค์ ์ถ๊ฐ๋ก ํ์ธํ๊ณ ๊ณต์ ํ๋ค.
ํ
์คํธ ์ผ์ด์ค์ ๋ฐฉํฅ์ฑ๋ ๋ช
ํํ ์ฌ์ ์ํ๋ค. QA ๋์ ํํ์ด์ง์ UI์ ๊ธฐ๋ฅ์ ์ฌ์ฉ์ ๊ด์ ์์ ๋ค์ ์ ๊ฒํด, ํ
์คํธ ์ผ์ด์ค์ ํ์ค์ฑ์ ๋์๋ค. ์ฒ์์๋ ํ์๊ฐ์
, ํ๊ธฐ๊ด๋ฆฌ, ๋ฐ์ดํฐ ์๊ฐํ์ฒ๋ผ ๊ธฐ๋ฅ ๋จ์๋ก ํ
์คํธ ์ผ์ด์ค๋ฅผ ๋๋ด๋๋ฐ, ์ค์ ์ฌ์ฉ์ ๊ด์ ์์๋ ์ด๋ฐ ๊ธฐ๋ฅ๋ค์ด ํญ ์์์ ํตํฉ์ ์ผ๋ก ๋์ํ๋ค๋ ์ ์ ๊นจ๋ฌ์๋ค. ๊ทธ๋์ ์ดํ์๋ ์ฌ์ดํธ ๊ตฌ์กฐ์ ๋ง์ถฐ 'ํ', '๊ฐ์ธ ํผ๋', 'ํ ํผ๋', 'ํ์คํ ๋ฆฌ' ํญ๋ณ๋ก ํ
์คํธ ์ผ์ด์ค๋ฅผ ๋ค์ ์ ๋ฆฌํ๋ค. ์ด ๋ฐฉํฅ ์ ํ ๋๋ถ์ ํ
์คํธ ํ์ค์ฑ์ด ๋์์ก๊ณ , ์๋ํ ์ฝ๋ ์์ฑ๋ ํ๊ฒฐ ์์ํด์ก๋ค.
์ ๊ทธ๋ฆฌ๊ณ ์ค๋ ์๊ฒ๋ ์ฌ์ค.. GitHub Desktop์ผ๋ก๋ GitLab์ ์ฌ์ฉํ ์ ์์๋ค..(์ฌ์ดํธ ๋ฐ๋ก๊ฐ๊ธฐ)
๐ 3/25 - 3์ผ์ฐจ ํ๊ณ (TC ์์ฑ ๋ง๋ฌด๋ฆฌ)
๊ฒฝ๋ ฅ์ด ์์ด์์ธ์ง ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ TC์ธ ํ์๊ฐ์
๊ณผ ๋ก๊ทธ์ธ ํํธ๋ฅผ ๋งก๊ฒ ๋์๊ณ , ๋๋ถ์ ๋๋ TC ์์ฑ์ ๊ฐ์ฅ ๋จผ์ ๋ง๋ฌด๋ฆฌํ ์ ์์๋ค. ์คํ 7์์ ์์ ๋ ์คํผ์ค ์์ ์๊ฐ์ ์์ฑํ TC์ ๋ํ ํผ๋๋ฐฑ์ ์์ฒญํ๊ธฐ๋ก ํ๊ณ , ์์ง ๋ค๋ฅธ ๋ถ๋ค์ TC ์์ฑ์ ์งํ ์ค์ด์๊ธฐ ๋๋ฌธ์, ๋จ๋ ์๊ฐ ๋์ GitLab ๊ฐ์ธ ํ๋ก์ ํธ๋ฅผ ํ์ฉํด GitLab๊ณผ Jenkins ์ฐ๋์ ๋์ ํด๋ณด์๋ค.
๋คํํ ์ค๋์ ์ฝ 3์๊ฐ ๋ง์ GitLab๊ณผ Jenkins๋ฅผ ์ ์์ ์ผ๋ก ์ฐ๋ํ๊ณ , GitLab ํ๋ก์ ํธ ๋ด Jenkinsfile์ ํตํด ํ์ดํ๋ผ์ธ์ด ์ ๋๋ก ๋์ํ๋ ๊ฒ๊น์ง ํ์ธํ ์ ์์๋ค. ์ด ์์
์ 2์ผ ๋๊ฒ ๋ถ์ก๊ณ ์์๋ ํฐ๋ผ, Webhook ์ฐ๋๊ณผ ๋น๋ ์ฑ๊ณต ๋ฉ์์ง๋ฅผ ๋ดค์ ๋ ์ ๋ง ์ง์ฌ์ผ๋ก ๊ธฐ๋ปค๋ค. ๊ทธ๋๋ ์ดํ ๋์ ์ฌ๋ฌ ๊ฐ์ง๋ฅผ ์๋ํด๋ณธ ๋๋ถ์ ๊ฒฐ๊ตญ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์๋ ๊ฒ ๊ฐ๋ค. ๊ทธ ๊ณผ์ ์์ ngrok์ด๋ผ๋ ํด๋ ์๋กญ๊ฒ ์๊ฒ ๋์ด ํ์ฉํ ์ ์์๋ค. ๋ด ๋ก์ปฌ ์๋ฒ(localhost:8080)๋ ์ธ๋ถ์์ ์ง์ ์ ๊ทผํ ์ ์์๊ธฐ ๋๋ฌธ์, ngrok์ ํตํด ์ธ๋ถ์์๋ ์ ์ ๊ฐ๋ฅํ ์ฃผ์๋ฅผ ์์ฑํด Webhook ์ฐ๊ฒฐ์ ํ
์คํธํ ์ ์์๋ค.
ํ์ฌ๋ Docker ํ๊ฒฝ์์ jenkins/jenkins ๊ณต์ ์ด๋ฏธ์ง๋ฅผ ๋ฐ๋ก ์ฌ์ฉํด Jenkins ์ปจํ
์ด๋๋ฅผ ์คํํ๊ณ ์์ผ๋ฉฐ, ํ์ด์ฌ์ด๋ ํฌ๋กฌ ๋ฑ์ ๋๊ตฌ๋ ๋งค๋ฒ ์๋์ผ๋ก ์ปจํ
์ด๋ ๋ด์ ์ค์นํด ์ฌ์ฉํ๊ณ ์๋ค. ํ์ง๋ง Dockerfile์ ํ์ฉํด ์ปค์คํ
์ด๋ฏธ์ง๋ฅผ ๋ง๋ค์ด๋๋ฉด, ์ด๋ฌํ ๋๊ตฌ๋ค์ด ๋ฏธ๋ฆฌ ์ค์น๋ Jenkins ์ปจํ
์ด๋๋ฅผ ์๋์ผ๋ก ์คํํ ์ ์์ด ๋งค๋ฒ ์๋ ์ค์นํ ํ์๊ฐ ์๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํ์๋ค๋ ๋์ผํ ํ๊ฒฝ์ ์์ฝ๊ฒ ๊ตฌ์ถํ ์ ์์ด ์ค์ ๊ณผ์ ์ด ํจ์ฌ ๊ฐํธํด์ง๋ค. ๊ทธ๋์ ์ด๋ฒ์ ์ง์ ๋์ ํด๋ณด๊ธฐ๋ก ํ๋ค.
๐ฅ Dockerfile ์์ฑ (Jenkins + Git Plugin + GitLab Plugin + Python3 + ๊ฐ์ ํ๊ฒฝ + Chrome)
[ Dockerfile ์์ฑ ]
FROM jenkins/jenkins:lts
USER root
# ํ์ ๋๊ตฌ ์ค์น
RUN apt-get update && apt-get install -y \
python3 python3-pip python3-venv \
git \
curl wget unzip gnupg2 && \
apt-get clean
# Chrome ์ค์น
RUN wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb && \
apt-get install -y ./google-chrome-stable_current_amd64.deb && \
rm google-chrome-stable_current_amd64.deb
# Git, GitLab ํ๋ฌ๊ทธ์ธ ์ง์ ์ค์น
RUN jenkins-plugin-cli --plugins \
git \
gitlab-plugin \
workflow-aggregator \
credentials-binding
USER jenkins
[ Dockerfile ๋น๋ (in VS Code ํฐ๋ฏธ๋) ]
์ Dockerfile์ด ๋ด๊ธด ํด๋๋ฅผ VS Code๋ก ์ด๊ธฐ
docker build -t {์ด๋ฏธ์ง ์ด๋ฆ} .
[ Jenkins ์ปจํ ์ด๋ ์คํ (in VS Code ํฐ๋ฏธ๋) ]
docker run -d -p {์ธ๋ถ ํฌํธ}:{์ปจํ ์ด๋ ๋ด๋ถ ํฌํธ} -p 50000:50000 --name {์ปจํ ์ด๋ ์ด๋ฆ} {์ด๋ฏธ์ง ์ด๋ฆ}
์ ์์ ์ผ๋ก ๋์ํ๋ค! Plugin๋ถํฐ Python3, ๊ฐ์ ํ๊ฒฝ, Chrome๊น์ง ๋ชจ๋ ์ค์น๋ Jenkins ์ปค์คํ
Dockerfile์ ๋น๋ํด ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๊ณ , ์ด ์ด๋ฏธ์ง๋ก ์ปจํ
์ด๋๋ฅผ ์คํํ ๋ค GitLab๊ณผ ์ฐ๋ํ๋, ํด๋น GitLab ํ๋ก์ ํธ ๋ด์ Jenkinsfile๋ ์ ์ธ์๋๋ค. ์ด์ ์ ๋ชจ๋ ๊ณผ์ ๋ค์ ์๋ตํ๊ณ ngrok ์ค์น์ Dockerfile๋ง ๊ณต์ ํ๋ฉด, ํ์๋ค๋ ๋น ๋ฅด๊ฒ ๋์ผํ ํ๊ฒฝ์ ๊ตฌ์ฑํ ์ ์์ ๊ฒ ๊ฐ๋ค.
TC ์์ฑ์ ์ค๋์ ๋ง์ง๋ง์ผ๋ก ์ต์ข ๋ง๋ฌด๋ฆฌํ๋ค. ์์งํ ๊ณ์ ์์ ํ๋ ค๋ฉด ๋๋ ์๊ณ , ๋ณธ๊ฒฉ์ ์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ ์ ํ๊ฒฝ ์ค์ ๋ถํฐ ํด์ผ ํ ์ผ๋ค์ด ๋ง๋ค ๋ณด๋, ์ธ์ ๊น์ง๋ TC๋ง ๋ถ์ก๊ณ ์์ ์๋ ์์๋ค. ์ฝ๋๋ฅผ ์์ฑํ๋ฉด์ ๋ฐ๊ฒฌํ ๋ถ๋ถ์ ๋ฐ๋ผ TC๋ฅผ ์์ ํด๋ ๊ด์ฐฎ์ ๊ฒ ๊ฐ์์, ์ค๋์ ๊ธฐ์ค์ผ๋ก ์ผ๋จ๋ฝ ์ง๊ธฐ๋ก ํ๋ค. ์ด์ฐจํผ ๊ฐ๋ฐ์ ํ๋ค ๋ณด๋ฉด ๋ฏธ์ฒ ์๊ฐํ์ง ๋ชปํ๋ ์์ธ๋ ํ๋ฆ๋ ์์ฐ์ค๋ฝ๊ฒ ๋๋ฌ๋ ํ ๋๊น..
๐ 3/26 - 4์ผ์ฐจ ํ๊ณ (์ฝ๋ ์์ฑ ์ ๊ต์ก ์งํ ๋ฐ ๊ตฌ์กฐ ์ค๊ณ)
๐ฅ ์์ฃผ ์ฌ์ฉํ๋ import
import time
import pytest
import selenium
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import NoSuchElementException, TimeoutException
ํ์๋ค์ด ์์ง Python ๋ฌธ๋ฒ(๋งค๊ฐ๋ณ์, ์ธ์, ํด๋์ค, ๊ฐ์ฒด, ์์ฑ์ ๋ฑ)์ ์ต์ํ์ง ์์ ์ํ๋ผ, ์ค๋์ ๋ด๊ฐ Live Share ๊ธฐ๋ฅ์ ํ์ฉํด ๊ฐ๋จํ ์ฝ๋ ๊ฐ์๋ฅผ ์งํํ๋ค. ํ์์๋ ์๋ก์ ํ๋ฉด์ ์ง์ ๋ณด์ฌ์ค์ผ ํ๋ ๋ถํธํจ์ด ์์์ง๋ง, Live Share๋ฅผ ํตํด ๋์ผํ ์ฝ๋์ ํจ๊ป ์ ์ํ๋ฉด์ ์ค์๊ฐ์ผ๋ก ์๋ก ์ง๋ฌธํ๊ณ ํผ๋๋ฐฑ ์ฃผ๊ณ ๋ฐ์ ์ ์์ด ํจ์ฌ ํจ์จ์ ์ผ๋ก ์ค๋ช
ํ ์ ์์๋ค.
๐ฅ mainPage.py
# Page Object ํด๋์ค (UI ์์ ๋ฐ ๋ฉ์๋ ์ ์)
import json
import time
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.webdriver import WebDriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from src.utils import mainLocators
class mainPage():
URL = "https://kdt-pt-1-pj-2-team03.elicecoding.com/signin"
def __init__(self, driver: WebDriver):
self.driver = driver
self.wait = WebDriverWait(self.driver, 10)
with open("credentials.json", "r", encoding="utf-8") as f:
self.userInfo = json.load(f)
def goToPage(self, depth2):
if (depth2 == "๋ฉ์ธ ํ์ด์ง"):
self.driver.get(self.URL)
elif (depth2 == "ํ์๊ฐ์
ํ์ด์ง"):
self.driver.get(self.URL)
self.getElement(mainLocators.REGISTER_BTN).click()
# ์ฒซ๋ฒ์งธ ์ฌ๊ธฐ์ url ๊ฒ์ฆ
elif (depth2 == "์ฑ ์ธ์ฆ ๊ถํ"):
pass
elif (depth2 == "๋ก๊ทธ์ธ ์ค๋ฅ ํ์ด์ง"):
pass
elif (depth2 == "์ธ์ ์ฌํญ ์์ฑ ํ์ด์ง"):
pass
elif (depth2 == "๋ก๊ทธ์ธ ํ์ด์ง"):
self.driver.get(mainLocators.URL)
self.getElement(mainLocators.LOGIN_BTN).click()
elif (depth2 == "๋น๋ฐ๋ฒํธ ์ฌ์ค์ ํ์ด์ง"):
pass
def getElement(self, element):
result = self.wait.until(EC.presence_of_element_located(element))
return result
๐ฅ test_mainPage.py
# ์ค์ ํ
์คํธ ์คํฌ๋ฆฝํธ (test_*.py ํ์)
import time
import pytest
import inspect
from src.pages.mainPage import mainPage
# ๊ตฌ๊ธ ์คํ๋ ๋ ์ํธ ์ฐธ๊ณ (depth2 ๊ธฐ์ค์ผ๋ก ํ๊ณ , ์์ test id ์ด ์ถ๊ฐ)
def test_login_001(createDriver):
try:
myMainPage = mainPage(createDriver)
myMainPage.goToPage("๋ฉ์ธ ํ์ด์ง")
time.sleep(2)
assert "signin" in myMainPage.driver.current_url
except Exception as e:
print(f"[โ] {e}")
def test_login_002(createDriver):
myMainPage = mainPage(createDriver)
myMainPage.goToPage("๋ก๊ทธ์ธ ํ์ด์ง")
time.sleep(2)
def test_login_003(createDriver):
myMainPage = mainPage(createDriver)
myMainPage.goToPage("ํ์๊ฐ์
ํ์ด์ง")
time.sleep(2)
๐ฅ mainLocators.py
from selenium.webdriver.common.by import By
# ๋ฉ์ธ ํ์ด์ง ์์
LOGIN_BTN = (By.XPATH, "//button[text()='๋ก๊ทธ์ธํ๊ธฐ']")
REGISTER_BTN = (By.XPATH, "//button[text()='ํ์๊ฐ์
']")
ID_INPUT = (By.ID, "username")
PW_INPUT = (By.ID, "password")
PW_TOGGLE_BTN = (By.XPATH, "//button[@data-action='toggle']") #์์ฑ์ @๋ก ์ฐพ๊ธฐ
PW_RESET = (By.XPATH, "//button[text()='๋น๋ฐ๋ฒํธ๋ฅผ ์์ผ์
จ๋์?']")
GOING_BTN = (By.XPATH, "//button[text()='๊ณ์ํ๊ธฐ']") #ํ
์คํธ๋ @์๋ต
์์ฑํ ํ
์คํธ ์ผ์ด์ค(TC)๋ฅผ ๋ฐํ์ผ๋ก ์๋ํ ์ฝ๋๋ฅผ ๊ตฌํํด์ผ ํ๋ฏ๋ก, TC ํ๋๋น ํ
์คํธ ํจ์ ํ๋์ฉ ๋งคํํด์ ์์ฑํ ๊ณํ์ด๋ค. ๊ทธ๋ฐ๋ฐ ๋ง์ ์ฝ๋๋ฅผ ์ง๋ค ๋ณด๋, ํ์ด์ง ์ด๋์ด๋ ๊ณตํต๋ ๋์๋ค์ด ๋ฐ๋ณต์ ์ผ๋ก ๋ฑ์ฅํด์ ์ฝ๋๊ฐ ๋๋ฌด ์ค๋ณต๋๋ ๋ฌธ์ ๊ฐ ์์๋ค. ๊ทธ๋์ ์ด๋ฐ ๋ฐ๋ณต๋๋ ๋ถ๋ถ์ ๋ณ๋์ ํจ์๋ก ๋ถ๋ฆฌํ๋ฉด ์ ์ง๋ณด์๋ ํจ์ฌ ์ฌ์์ง๊ณ , ์ ์ฒด์ ์ธ ์ฝ๋ ๊ตฌ์กฐ๋ ๋ ๊น๋ํด์ง ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์ด goToPage() ํจ์๋ฅผ ๋ง๋ค์๋ค.
์คํผ์ค์์ ์๊ฐ์๋ ์ค๋ณต๋๋ ํ์ด์ง ์ด๋ ๊ณผ์ ์ ํจ์๋ก ๋ถ๋ฆฌํ ๋ฐฉ์์ ๋ํด ์ฝ์น๋๊ป ํผ๋๋ฐฑ์ ์์ฒญ๋๋ ธ๋ค. ์๋ ์ค๋ฌด์์๋ ํ
์คํธ ์ผ์ด์ค(TC) ํ๋๋น ํ
์คํธ ํจ์ ํ๋๋ก ๊ตฌํํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ด๋ฉฐ, ์๋ํ ํ
์คํธ์์๋ TC๊ฐ ์ฝ๋ ๊ตฌ์กฐ์ ๊ธฐ์ค์ด ๋๋ฏ๋ก, ๋ด๊ฐ ์๋ํ ์ค๋ณต ๋ก์ง ๋ถ๋ฆฌ ๋ฐฉ์์ ๋์์ง ์๋ค๊ณ ํ์
จ๋ค.
๋ค๋ง ๋ณธ์ธ์ด๋ผ๋ฉด goToPage()์ ๊ฐ์ ๊ณตํต ์ด๋ ํจ์๋ Util ๋ชจ๋๋ก ๋ฐ๋ก ๋นผ๊ณ , ๊ฐ ํ์ด์ง ํด๋์ค ๋ด์์๋ goToSecondaryPage()์ฒ๋ผ ํด๋น ํ์ด์ง ๋ด์ ์ธ๋ถ ์ด๋์ ๋ด๋ถ ํจ์๋ก ์ฒ๋ฆฌํ ๊ฒ ๊ฐ๋ค๊ณ ํ์
จ๋ค. ์ด ๋ฐฉ์์ด ๋ ํจ์จ์ ์ธ์ง์ ๋ํด์๋ ๊ฒํ ํด๋ณผ ํ์๊ฐ ์์ ๊ฒ ๊ฐ๋ค.
ํ์ด์ง ์์ ๊ด๋ จ ๋ณ์๋ฅผ mainPage.py์ test_mainPage.py ๋ ํ์ผ์์ ๋ชจ๋ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ํด๋น ๋ณ์๋ค์ ๋ณ๋ Util ๋ชจ๋๋ก ๋ถ๋ฆฌํด ๊ด๋ฆฌํ๋ ๊ฒ์ด ๋ ๊น๋ํ๋ค๋ ํผ๋๋ฐฑ์ ๋ฐ์๋ค. ์ด์ ๋ฐ๋ผ ์ผ๋ถ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ ํด, ์์๋ฅผ Util์์ importํด ์ฌ์ฉํ๋ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ๋ค. ๋ํ ํ์ด์ง๋ณ๋ก locator ํ์ผ์ ๋ฐ๋ก ๊ด๋ฆฌํ๋ฉด, ์์ ๋ณ๊ฒฝ ์ ์ ์ง๋ณด์๊ฐ ์ฌ์์ง๊ณ , ํ์ํ ์์๋ import๋ง์ผ๋ก ํธ๋ฆฌํ๊ฒ ์ ๊ทผํ ์ ์๋ค๋ ์ฅ์ ๋ ์์ด ์ด ๊ตฌ์กฐ๋ฅผ ์ฑํํ๋ค.
ํนํ ๋๋ ํด๋น ์์๊ฐ ์ด๋ค ๋ฐฉ์(id, name, xpath ๋ฑ)์ผ๋ก ์ ์๋์๋์ง๊น์ง ํจ๊ป ๋ช
์ํ๋ ๊ฒ์ด ์ข๋ค๊ณ ํ๋จํด, locator๋ฅผ ํํ ํํ๋ก ์ ์ํ๋ค. ์ด ํํ์ wait ๊ธฐ๋ฅ์ ํฌํจํ getElement() ํจ์์ ๊ทธ๋๋ก ๋๊ฒจ ์ฌ์ฉํ ์ ์๊ฒ ์ค๊ณํ๋ค. ์ด๋ ๊ฒ ์ ๋ฆฌํ ๊ตฌ์กฐ๋ ์ฌ์ฌ์ฉ์ฑ, ๊ฐ๋
์ฑ, ์ ์ง๋ณด์ ์ธก๋ฉด์์ ๋ชจ๋ ๋ง์กฑ์ค๋ฌ์ ๊ณ , ๋ฌด์๋ณด๋ค ์ฝ๋ ์์ฑ ์ ์๊ฐ์ ํ๋ฆ์ด ๋ช
ํํด์ ธ์ ๊ฐ์ธ์ ์ผ๋ก๋ ๋งค์ฐ ๋ง์กฑ์ค๋ฌ์ด ๋ฆฌํฉํ ๋ง์ด์๋ค.
๐ 3/27 - 5์ผ์ฐจ ํ๊ณ (TC๋ฅผ ๋ฐํ์ผ๋ก ๋ณธ๊ฒฉ์ ์ธ ์๋ํ ์ฝ๋ ์์ฑ)
์ค๋์ ํ์๋ถ๋ค๊ป์ ๋ก๊ทธ์ธ/ํ์๊ฐ์
ํ์ด์ง์ UI ์์๋ค์ ๋ชจ๋ ์๋ณํด์ฃผ์
จ๊ณ , ํด๋น ์์๋ค์ ๊ณตํต Util ํ์ผ๋ก ๋ถ๋ฆฌํ์ฌ ์ ๋ฆฌํ๋ค. ๋๋ ์ด ๊ณผ์ ์์ ๊ธฐ์กด ํ
์คํธ ์ผ์ด์ค๋ค์ ํจ๊ป ๊ฒํ ํ๋ฉด์, ํ๋์ ํ
์คํธ ํจ์ ์์์ ๋์์ ๊ฒ์ฆํ๋ ๊ฒ์ด ํจ๊ณผ์ ์ธ ์ผ์ด์ค๋ค์ ๋ฌถ์ด ์ฌ๊ตฌ์ฑํ๋ค. ๊ทธ ๊ฒฐ๊ณผ, ๋ก๊ทธ์ธ/ํ์๊ฐ์
ํ์ด์ง ๊ด๋ จ ์ด 64๊ฐ์ ํ
์คํธ ์ผ์ด์ค๋ฅผ ๋ถ์ํด 25๊ฐ์ ํ
์คํธ ํจ์๋ก ๋๋์๊ณ , ๊ฐ ๋ฌถ์์๋ ๋ณ๋์ ํ
์คํธ ํจ์ ID๋ฅผ ๋ถ์ฌํด ์ฒด๊ณ์ ์ผ๋ก ๊ด๋ฆฌํ๋ค. ๋ํ, ์ค๋ณต๋๋ ๋์์ ๋ณ๋ ํจ์๋ก ๋ถ๋ฆฌํด ์ฌ์ฌ์ฉํ ์ ์๋๋ก ์ ๋ฆฌํ๋ค.
์ด๋ ๊ฒ ๊ธฐ๋ณธ์ ์ธ ์ค๋น๋ฅผ ๋ง์น ๋ค, ๋ณธ๊ฒฉ์ ์ผ๋ก ํ
์คํธ ์๋ํ ์ฝ๋ ์์ฑ์ ์์ํ๋ค. ์์ง์ ๊ต์ก ๋ฐ ์ฐ์ต ๋จ๊ณ์ด๊ธฐ๋ ํด์, ํ์๋ค๊ณผ ๋ก๊ทธ์ธ/ํ์๊ฐ์
ํ์ด์ง๋ฅผ ํจ๊ป ์์
ํ๋ฉฐ ํ์
์ ์๋ํ๋ค. ํ์ง๋ง ์ด ๊ณผ์ ์์ Live Share์ ํ๊ณ๋ฅผ ๋ผ์ ๋ฆฌ๊ฒ ๋๊ผ๋ค. ๊ฐ์์ ๋ก์ปฌ ํ๊ฒฝ์์๋ ํ
์คํธ ์คํ์ด ์ด๋ ค์ ๊ธฐ ๋๋ฌธ์, ๋ชจ๋ ํ
์คํธ ์คํ์ ๋ด ์ปดํจํฐ์์๋ง ๊ฐ๋ฅํ๊ณ , ํ์๋ถ๋ค์ด ํ
์คํธ๋ฅผ ์์ฒญํ ๋๋ง๋ค ๋ด ์์
์ ์ค๋จ๋ ์๋ฐ์ ์์ด ์ฝ๋ ์์ฑ ์๋๊ฐ ํ์ ํ ๋๋ ค์ก๋ค.
๊ฒ๋ค๊ฐ ํ
์คํธ ๋์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด, ์ค๋ฅ ์์ธ๊ณผ ๊ฐ๋
์ ์ค๋ช
ํ๊ณ ์ง์ ์์ ์ ๋์์ผ ํ๊ธฐ ๋๋ฌธ์ ์์
์ ๋ํ ์ง์ค๋๊ฐ ์์ฃผ ๋ถ์ฐ๋์๋ค. ๋ฌผ๋ก ํ์๋ค์ ์๋ก ๋ค๋ฅธ ์๋ จ๋๋ฅผ ๊ณ ๋ คํด ํจ๊ป ๊ณต๋ถํ๋ฉฐ ์งํํ ์ ์ ์๋ฏธ ์์์ง๋ง, ์ง๊ธ์ ๋จ์ํ ํ์ต์ด ์๋ ์ค์ ๊ฒฐ๊ณผ๋ฌผ์ ๋ง๋ค์ด์ผ ํ๋ ํ๋ก์ ํธ์ด๊ธฐ ๋๋ฌธ์, ์ญํ ์ ๋ถ๋ดํด ๋ณด๋ค ํจ์จ์ ์ผ๋ก ์์
์ ์งํํ๋ ๊ฒ์ด ํ์ํ๋ค๊ณ ๋๊ผ๋ค.
๋จ์ ์๊ฐ์ด ๋ง์ง ์๋ค๋ ํ์ค์ ์ธ ์ ์ฝ๋ ์์ด, ๊ณ์ ํจ๊ป ๋ถ์ก๊ณ ์์
ํ๊ธฐ์ ์ด๋ ค์์ด ์์๋ค. ๊ทธ๋์ ๊ฐ์๊ฐ ์์ฑํ ํ
์คํธ ์ผ์ด์ค(TC)์ ๊ด๋ จ๋ ํ์ด์ง๋ฅผ ๊ฐ๋ณ์ ์ผ๋ก ๋งก์ ์๋ํ ๊ตฌํ์ ์งํํ๋ ๋ฐฉ์์ผ๋ก ์ ๋ต์ ๋ณ๊ฒฝํ๋ค.
๋ด์ผ๋ถํฐ๋ ๋ณธ๊ฒฉ์ ์ผ๋ก ๊ฐ์์ TC์ ๊ด๋ จ๋ ์ฝ๋ ๊ตฌํ์ด ์์๋ ์์ ์ด์๊ธฐ ๋๋ฌธ์, ๋๋ ํ์๋ค์ด ๋ฐ๋ก ์์ ์ ํฌ์ ๋ ์ ์๋๋ก ๊ฐ์์ ์ฝ๋ ํ์ ๋ฏธ๋ฆฌ ์ก์์ฃผ๋ ์์ ๋ ํจ๊ป ์งํํ๋ค. ๊ฐ ํ์ด์ง๋ณ๋ก ํ์ํ ํ์ผ์ ์์ฑํ๊ณ , ํด๋์ค ๊ตฌ์กฐ์ ์์ฑ์ ์ธํ , ์ ์ฒด์ ์ธ ํ์ ๋จผ์ ๊ตฌ์ฑํด ๋์๋ค. ์ด๋ ๊ฒ ๊ธฐ๋ณธ ๊ณจ๊ฒฉ์ด ์กํ ์ํ์์ ์์ํ๋ฉด ํผ๋์ ์ค์ด๊ณ , ๊ฐ์ ๊ตฌํ์ ์ข ๋ ์ง์คํ ์ ์์ ๊ฑฐ๋ผ ํ๋จํ๋ค.
๋๋ ํ์๊ฐ์
๊ณผ ๋ก๊ทธ์ธ์ด ํฌํจ๋ ๋ฉ์ธ ํ์ด์ง์ ํ
์คํธ ์ผ์ด์ค๋ฅผ ๋ด๋นํ๊ณ ์์๊ธฐ ๋๋ฌธ์, ํด๋น ํ์ด์ง๋ถํฐ ๋น ๋ฅด๊ฒ ์๋ํ ์ฝ๋๋ฅผ ์์ฑํ ๋ค, ๋ค๋ฅธ ํ์๋ค์ด ๋งก์ ํ์ด์ง ๊ตฌํ๋ ๋์ธ ๊ณํ์ด๋ค. ์ด๋ ๊ฒ ์ญํ ์ ๋ถ๋ฐฐํ๋ฉด ์ ์ฒด ์งํ ์๋๋ฅผ ๋์ผ ์ ์๊ณ , ๊ฒฐ๊ณผ๋ฌผ ์์ฑ์๋ ๋ณด๋ค ๊ฐ๊น์์ง ์ ์์ ๊ฒ ๊ฐ๋ค๋ ํ๋จ์ด ๋ค์๋ค.
๊ทธ๋ฆฌ๊ณ ๊ฐ์ ํ์ด์ง๋ฅผ ๋งก์ ์์
์ ์งํํ๋ ค๋ฉด, ๊ธฐ๋ณธ ๊ฐ๋
์ ๋ํ ์ ํํ ์ดํด๊ฐ ํ์์ ์ด๋ผ๊ณ ํ๋จํ๋ค. ํนํ ํ์๋ถ๋ค๊ป์ ํท๊ฐ๋ คํ์๋ ํด๋์ค, ๊ฐ์ฒด, self, ์์ฑ์ ๊ฐ์ ๊ฐ๋
์ ๋ฐ๋ณต์ ์ผ๋ก ์ค๋ช
ํ๋ ์ํฉ์ด ์์ฃผ ๋ฐ์ํ๊ณ , ๊ฐ์ ๋ด์ฉ์ ์ฌ๋ฌ ๋ฒ ์ค๋ช
ํ๋ ๊ฒ์ด ์ ์ ๋นํจ์จ์ ์ด๋ผ๋ ์๊ฐ์ด ๋ค์๋ค.
๊ทธ๋์ ์ค๋์ ๋ฐค 10์ 30๋ถ์ ์ง์ ๋์ฐฉํ์๋ง์, ํผ๊ณคํ ๋ชธ์ ์ด๋๊ณ ์์ดํจ๋๋ฅผ ๊บผ๋ด ๋ค์๋ค. ๊ทธ๋ฆฌ๊ณ ๊ตฟ๋
ธํธ๋ฅผ ์ด์ฉํด ํด๋น ๊ฐ๋
๋ค์ ์ ๋ฆฌํ PDF ์๋ฃ๋ฅผ ๋ง๋ค์ด ํ์๋ค๊ณผ ๊ณต์ ํ๋ค. ์ฌ์ค ๋๋ ํ๋ก๊ทธ๋๋ฐ์ ์ฒ์ ๋ฐฐ์ธ ๋ ์ด ๊ฐ๋
๋ค์ด ์ ๋ง ํท๊ฐ๋ ธ๋ ๊ธฐ์ต์ด ์์ด์, ํ์๋ค์ ์ด๋ ค์์ ์ถฉ๋ถํ ๊ณต๊ฐํ ์ ์์๋ค.
ํ ๋ฒ ์ ๋ฆฌํด๋๋ฉด ์ดํ ์ค๋ช
์ ๋๋ ์๊ฐ๋ ์ค์ด๋ค๊ณ , ํ์๋ค๋ ๊ฐ์ ๊ตฌํ์ ์งํํ๋ ๋ฐ ํจ์ฌ ์์ํ ๊ฒ ๊ฐ์ ๋ฆ์ ์๊ฐ์ด์์ง๋ง ์๋๋ฌ ์ ๋ฆฌํด ๊ณต์ ํ๊ฒ ๋๋ค.
๐ 3/28 - 6์ผ์ฐจ ํ๊ณ (๋ฉ์ธ ํ์ด์ง ์๋ํ ํ ์คํธ ๊ตฌํ ์๋ฃ)
์ค๋์ ์ด์ ํ์๋ถ๋ค๊ป์ ์ฐพ์์ฃผ์ ๋ฉ์ธ ํ์ด์ง ๋ด ์์๋ค์ ๋ฐํ์ผ๋ก, ๋ณ์๋ช
์ ํ์ด์ง ๊ตฌ์กฐ์ ๋ง๊ฒ ์ ๋ฐ์ ์ผ๋ก ์์ ํ๋ค. ๊ฐ๋
์ฑ๊ณผ ์ ์ง๋ณด์ ํธ์์ฑ์ ๊ณ ๋ คํด ์ด๋ฆ์ ์ผ๊ด๋๊ฒ ์ ๋ฆฌํ์ผ๋ฉฐ, ๊ทธ ๊ณผ์ ์์ ์๋ชป ์ง์ ๋ ์์๋ค๋ ๊ฝค ๋ง์ ๋ด๊ฐ ์ง์ ํ๋์ฉ ํ์ด์ง๋ฅผ ํ์ธํ๋ฉด์ ์ ๋ถ ๊ฒํ ํ๊ณ ์์ ํ๋ค. ์์ ์ ๋ฆฌ๊ฐ ๋ง๋ฌด๋ฆฌ๋ ๋ค์๋ ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ฉ์ธ ํ์ด์ง์ ๊ด๋ จ๋ ์ด 25๊ฐ์ ํ
์คํธ ํจ์ ๊ตฌํ์ ์๋ฃํ ์ ์์๋ค.
๊ฐ ํ
์คํธ ์ผ์ด์ค๋ง๋ค ํ๋์ ํ
์คํธ ํจ์๋ฅผ ๊ตฌํํ๊ธฐ ๋๋ฌธ์, ํ
์คํธ ํจ์ ์ด๋ฆ์ ๊ตฌ๊ธ ์คํ๋ ๋์ํธ์ ์ ๋ฆฌ๋ ํ
์คํธ ํจ์ ID์ ๋์ผํ๊ฒ ๋ง์ถ์๋ค. ๋ํ, ํ
์คํธ๊ฐ pass๋ ๊ฒฝ์ฐ ํด๋น ํจ์ ์ด๋ฆ์ ์๋์ผ๋ก ๋ถ๋ฌ์ฌ ์ ์๋๋ก inspect ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ๋ ๋ฐฉ์์ ์ ์ํ๊ณ , ๋ชจ๋๊ฐ ๊ทธ ๋ฐฉ์์ ๋ง์กฑํ์ฌ ์ ์์ผ๋ก ์ฑํํ๊ฒ ๋์๋ค. ์ด๋ฅผ ํตํด ์๋ํ ๊ฒฐ๊ณผ ๋ก๊ทธ๋ฅผ ํ์ธํ๋ฉด์, ์ด๋ค ํ
์คํธ ์ผ์ด์ค๊ฐ ํต๊ณผ(pass)๋์๋์ง ํ
์คํธ ํจ์ ID ๊ธฐ์ค์ผ๋ก ์ง๊ด์ ์ผ๋ก ํ์
ํ ์ ์์ด ํ
์คํธ ๊ฒฐ๊ณผ ๋ถ์์ด ํจ์ฌ ์์ํด์ง ๊ฒ์ผ๋ก ๊ธฐ๋๋๋ค.
์ฌ๋ผ์ด๋ ์๋ํ์์๋ ๊ฝค ๋ง์ ์๊ฐ์ ํ๋นํ์ง๋ง, ๊ฒฐ๊ตญ ActionChains๋ฅผ ํ์ฉํด ์ํ๋ ๋์์ ๊ตฌํํ๋ ๋ฐ ์ฑ๊ณตํ๋ค. ์ฒ์์๋ ์ ๋๋ก ์๋ํ์ง ์์ ๋นํฉํ์ง๋ง, ์ง์ ํ๋์ฉ ํ
์คํธํด๋ณด๋ฉฐ ‘๋ด๊ฐ ์ด๋ค ํ๋์ ํ์ ๋ ์์์ ์์ฑ๊ฐ์ด ์ด๋ป๊ฒ ๋ฐ๋๋์ง’, ‘๊ทธ ๋ณ๊ฒฝ๋ ์์ฑ๊ฐ์ ๊ธฐ์ค์ผ๋ก ํ
์คํธ๊ฐ ์ฑ๊ณตํ๋์ง๋ฅผ ์ด๋ป๊ฒ ๊ฒ์ฆํ ์ ์์์ง’, ‘ํด๋น ์์์ ์์ฑ๊ฐ ์ค ์ด๋ค ๊ฐ์ ๊ธฐ์ค์ผ๋ก ํ๋ฉด ๋ ์ ํํ๊ณ ์์ ์ ์ผ๋ก ์์๋ฅผ ์ฐพ์ ์ ์์์ง’ ๊ฐ์ ๋ถ๋ถ๋ค์ ํ๋์ฉ ์ฒด๋ํด๋๊ฐ๊ณ ์๋ค๋ ๋๋์ด ๋ค์๋ค. ์์ ์๋ ๋จ์ํ ๋ณด์ด๋ UI๋ง ๋ฐ๋ผ๊ฐ๋ค๋ฉด, ์ด์ ๋ ์ค์ ์์์ ๊ตฌ์กฐ์ ๋ณํ๋ฅผ ์ง์ ํ์
ํ๊ณ ํ์ฉํ ์ ์๋ ์์ค์ผ๋ก ์ฑ์ฅํ๊ณ ์๋ค๋ ๊ฒ ๋๊ปด์ ธ์ ๋ฟ๋ฏํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ค๋ Jenkins ๊ด๋ จํด์ ์ค์ํ ๊ณต์ง๊ฐ ์ ๋ฌ๋๋ค. ๋ค๋ฅธ ํ์ ํ ๋ถ์ด GitLab ๋ ํฌ์งํ ๋ฆฌ์ Jenkins๋ฅผ SSH ๋ฐฉ์์ผ๋ก ์ฐ๋ํ๋ ์๋๋ฅผ ํ์
จ๋ ๋ชจ์์ธ๋ฐ, ์ด ๋ฐฉ์์ GitLab์ ๊ณต์ ๋ฌ๋๊ฐ ์๋์ผ๋ก ์๋ํ๋ฉด์ Merge ์ ์ถฉ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค๊ณ ํ๋ค. ์ด์ ๋ฐ๋ผ ์ฝ์น๋๊ป์ ์ธ ๊ฐ์ง ๋์ ๋ฐฉ๋ฒ์ ์๋ดํด์ฃผ์
จ๋ค.
- Ngrok์ ์ด์ฉํ ๋ก์ปฌ ํฐ๋๋ง ๋ฐฉ์
→ ์ด๊ฑด ๋ฐ๋ก ๋ด๊ฐ ๋ฉฐ์น ์ ์ ์ง์ ์๋ํด์ ์ฑ๊ณตํ๋ ๋ฐฉ๋ฒ! ๋ค๋ง ์ด ๋ฐฉ์์ Ngrok์ ํน์ฑ์ ์ฃผ์๊ฐ ๋งค๋ฒ ๋ฐ๋๊ธฐ ๋๋ฌธ์, ์ง์์ ์ธ ์ฌ์ฉ์๋ ๋ค์ ๋ถ์์ ํ ๋ฉด์ด ์๋ค. - ๊ณต์ ์๋ฒ๋ฅผ ์ด์ฉํ CI ๊ตฌ์ถ (์ถ์ฒ)
→ ๊ฐ ํ๋ณ๋ก ๊ณต์ ์๋ฒ๊ฐ ์ ๊ณต๋ ์์ ์ด๋ฉฐ, ์ธํ ์ด ์๋ฃ๋๋ ๋๋ก ํ๋ณ ์๋ด๊ฐ ์์ ์์ ์ด๋ผ๊ณ ํ๋ค. ์ด ๋ฐฉ๋ฒ์ด ๊ฐ์ฅ ์์ ์ ์ด๋ผ ์ถํ ๋ค์ ์๋ํด๋ด์ผ ํ ๊ฒ ๊ฐ๋ค. - GitLab ๊ณต์ ๋ฌ๋๋ฅผ ๋นํ์ฑํํ ๋ค SSH ๋ฐฉ์์ผ๋ก ์ฐ๋
→ ๊ณต์ ๋ฌ๋๊ฐ ์๋์ผ๋ก ์๋ํ์ง ์๋๋ก ์ค์ ํ ํ, SSH ๋ฐฉ์์ผ๋ก Jenkins์ GitLab์ ์ฐ๊ฒฐํ๋ ๋ฐฉ์์ด๋ค.
์คํผ์ค์์ ์๊ฐ์ ์ฝ์น๋๊ป์ ์ค๋ฌด์์ ์์๋ฅผ ์ฐพ๋ ๋ฐฉ์์ ๋ํด ์ค๋ช
ํด์ฃผ์
จ๋ค. ์ค์ ๋ก๋ ์ ์ฒด ์ปจํ
์ด๋๋ฅผ ๋จผ์ ๋ถ๋ฌ์จ ๋ค, ๊ทธ ์์์ ํ์ํ ์์์ ์ ๊ทผํ๋ ์์ผ๋ก ์์
ํ๋ค๊ณ ํ์
จ๊ณ , ์ด๋ฐ ๋ฐฉ์์ด ๋ ์์ ์ ์ด๊ณ ์ ์ง๋ณด์์๋ ์ ๋ฆฌํ๋ค๊ณ ํ์
จ๋ค.
๋ํ ์ค๋ฌด์์๋ ํ
์คํธ๋ฅผ ์งํํ ๋, ‘ํด๋น ํ์ด์ง์ <h1> ํ๊ทธ๊ฐ ๋ช ๊ฐ ์๋์ง’์ฒ๋ผ ๋จ์ํ ๊ธฐ์ค์ ํ์ฉํ๋ ๊ฒฝ์ฐ๋ ๋ง๋ค๋ ํ๋ ์ฃผ์
จ๋ค. ์ด์ ๋ ๊ฐ๋จํ๋ค. ์๋ฅผ ๋ค์ด, ๊ฐ๋ฐ์๊ฐ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ฉด์ <h1> ํ๊ทธ๊ฐ ํ๋ ๋ ์๊ธฐ๋ฉด, ํ
์คํธ์์๋ ๊ทธ ๋ณํ๋ฅผ ์์ฐ์ค๋ฝ๊ฒ ๊ฐ์งํ ์ ์๊ธฐ ๋๋ฌธ์, “์, ๋ญ๊ฐ ์ถ๊ฐ๋๊ตฌ๋” ํ๊ณ ๋น ๋ฅด๊ฒ ํ์
ํ ์ ์๋ค๋ ๊ฒ์ด๋ค. ์ด์ฒ๋ผ ํ์ด์ง ๊ตฌ์กฐ ๋ณ๊ฒฝ์ ์ ์ฐํ๊ฒ ๋์ํ ์ ์๊ณ , ์ธ๋ถ ์์๋ฅผ ์ผ์ผ์ด ์ง์ ํ์ง ์์๋ ๋ณํ ๊ฐ์ง๊ฐ ๊ฐ๋ฅํ ๋ฐฉ์์ด ์คํ๋ ค ์ค๋ฌด์์๋ ๋ ์ค์ฉ์ ์ผ ์ ์๋ค๋ ์ ์ด ์ธ์ ๊น์๋ค.
๐ 3/29 - ๊ฐ์ธ ๊ณต๋ถ (๊ฐ์ธ ํผ๋ ํญ ์๋ํ ํ ์คํธ ๊ตฌํ ์์)
์ค๋์ ํ์ ์ธ ๋ถ์ด ๊ฐ์ ๋งก์ ํ ํญ, ํ ํผ๋ ํญ, ํ์คํ ๋ฆฌ ํญ์ ์ ์ธํ๊ณ , ์์ง ์๋ฌด๋ ์์
ํ๊ณ ์์ง ์์ ๊ฐ์ธ ํผ๋ ํญ์ ์๋ํ ํ
์คํธ๋ฅผ ๋งก์ ์งํํ๋ค. ์๋ก ๋ค๋ฅธ ์ฅ์์์ ์์
์ค์ด๊ธฐ ๋๋ฌธ์, ๋์ผํ ์์ญ์ ๋์์ ์์
ํ๋ฉด ์ถฉ๋์ด ๋ฐ์ํ ์ ์์ด ๊ฐ๋ฅํ ๊ฒน์น์ง ์๋ ์์ญ์ ๋งก๋ ๊ฒ ์์ ํ๋ค๊ณ ํ๋จํ๋ค. ๊ทธ๋์ ๊ฐ์ธ ํผ๋ ํญ์ ๋งก์ ์ค๋ ํ๋ฃจ ์ฝ 10์๊ฐ์ ์ง์ค ํฌ์ํ๋ค.
์๋ํ ํ
์คํธ๋ฅผ ๊ตฌํํ๊ธฐ ์ , ๊ธฐ์กด ํ
์คํธ ์ผ์ด์ค๋ค์ ํจ๊ป ๊ฒํ ํ๋ฉด์, ํ๋์ ํ
์คํธ ํจ์ ์์์ ๋์์ ๊ฒ์ฆํ๋ ๊ฒ์ด ํจ๊ณผ์ ์ธ ์ผ์ด์ค๋ค์ ๋ฌถ์ด ์ฌ๊ตฌ์ฑํ๋ค. ๊ทธ ๊ฒฐ๊ณผ, ๊ฐ์ธ ํผ๋ ํญ๊ณผ ๊ด๋ จ๋ ์ด 111๊ฐ์ ํ
์คํธ ์ผ์ด์ค๋ฅผ ๋ถ์ํด 17๊ฐ์ ํ
์คํธ ํจ์๋ก ๋๋์๊ณ , ๊ฐ ๋ฌถ์์๋ ๋ณ๋์ ํ
์คํธ ํจ์ ID๋ฅผ ๋ถ์ฌํด ์ฒด๊ณ์ ์ผ๋ก ๊ด๋ฆฌํ๋ค.
๊ทธ๋ฐ๋ฐ ๋ก๊ทธ์ธ/ํ์๊ฐ์
ํ์ด์ง์ ๋นํด ๊ฐ์ธ ํผ๋ ํญ์ ์์๋ฅผ ์ฐพ๋ ๊ฒ ์๋นํ ๊น๋ค๋ก์ ๋ค.
- visible ๋๋ clickable ์ํ๊ฐ ๋ ๋๊น์ง ๋ช ์์ ์ผ๋ก ๊ธฐ๋ค๋ ค์ผ ํ๋ ์์๋ค์ด ์์๊ณ ,
- scroll๋ก ํ๋ฉด์ ๋ด๋ ค์ผ๋ง ์ ๊ทผ ๊ฐ๋ฅํ ์์๋ค๋ ์กด์ฌํ๋ค.
์ด๋ก ์ธํด ์์๋ฅผ ์์ ์ ์ผ๋ก ํ์ํ๊ณ ์๋ณํ๋ ๋ฐ์๋ง ์ ์ฒด ์์
์๊ฐ์ ์ ๋ฐ ์ด์์ด ์์๋๋ค. ๊ฒ๋ค๊ฐ ์ค๋ ์ฐพ์ ์์๋ค๋ ์ ์ฒด๊ฐ ์๋๋ผ, ํ
์คํธ ํจ์๋ฅผ ์์ฑํ๋ ๋์ค ๊ทธ๋๊ทธ๋ ํ์ํ ์์๋ง ํ์ํ ์์ค์ด์๋ค. ๊ฒฐ๊ตญ ์ค๋ ํ๋ฃจ ๋์์ ์ด 17๊ฐ์ ํ
์คํธ ํจ์ ์ค ๋จ 5๊ฐ๋ง ๊ตฌํํ ์ ์์์ง๋ง, ๊ทธ ๊ณผ์ ์์ ๋๋ ์ ๋ ๋ง์๋ค. ํนํ ‘์์ ์ฐพ๊ธฐ’์ ๋ํ ๊ฐ๊ฐ์ด ํ์คํ ํฅ์๋์๋ค๋ ์ ์์ ๊ธฐ์ ์ ์ธ ์ฑ์ฅ์ ๋ถ๋ช
ํ ํ๋ฃจ์๋ค. ์๋๋ ๊ธฐ๋๋งํผ ๋น ๋ฅด์ง ์์์ง๋ง, ์์ฑ๋๋ฅผ ์ํ ๋ฐํ์ ํผํผํ ๋ค์ก๋ค๊ณ ์๊ฐํ๋ค.
๐ฅ ์์ ์ฐพ๊ธฐ Tip
• /.. : ํด๋น ์์์ ๋ถ๋ชจ
• /preceding-sibling : ํด๋น ์์์ ๊ฐ์ ๋ถ๋ชจ ์๋, ์์ ์๋ ํ์
• /following-sibling : ํด๋น ์์์ ๊ฐ์ ๋ถ๋ชจ ์๋, ๋ค์ ์๋ ํ์
• <svg>๋ HTML์ด ์๋๋ผ SVG ๋ค์์คํ์ด์ค(XML ๊ธฐ๋ฐ)
> //svg ๋๋ //preceding-sibling::svg ์ฒ๋ผ ์ฌ์ฉ์ ์คํจ ํ๋ฅ ๋์
> *[name()='svg'] ์ฒ๋ผ ๋ค์์คํ์ด์ค ๋ฌด์ํ๊ณ svg ํ๊ทธ๋ก ์ ํํ๊ฒ ์ธ์
> ๋ค์์คํ์ด์ค : HTML์ด๋ XML์์ ๊ฐ์ ์ด๋ฆ์ ํ๊ทธ๊ฐ ์ถฉ๋ํ์ง ์๋๋ก ๊ตฌ๋ถํด์ฃผ๋ ๊ฒ
๐ 3/30 - ํ ๋ชจ์ (์ด์ ์์ ์ด์ด ๊ฐ์ ์๋ํ ์ฝ๋ ๊ฐ๋ฐ)
์ค๋์ ํ์ผ ์์
๋ง์ผ๋ก๋ ์๊ฐ์ด ๋ถ์กฑํ ๊ฒ ๊ฐ์, ์ฃผ๋ง์์๋ ํ์ ๋ชจ๋๊ฐ ์๊ฐ์ ๋ด์ด ํจ๊ป ๋ชจ์๋ค. ๊ฐ์ ๋งก์ ํ์ด์ง์ ๊ธฐ๋ฅ ๊ตฌํ์ ๊ณ์ ์ด์ด๊ฐ๊ณ , ๋๋ ์ฌ์ ํ ๊ฐ์ธ ํผ๋ ํญ ์๋ํ ํจ์ ๊ตฌํ์ ์ง์ค์ ์ผ๋ก ์๊ฐ์ ํฌ์ํ๋ค.
์์
์ด ์๊ฐ๋ณด๋ค ํจ์จ์ ์ผ๋ก ์งํ๋ ์ด์ ์ค ํ๋๋, ํ์๋ค์ด ๊ฐ์ ๋ฏธ๋ฆฌ ์ ์ ๋ฆฌํด๋ ์์๋ค ๋๋ถ์ด์๋ค. ๋ ์ญ์ ์ฌ์ ์ ์ ๋ฆฌํด๋ ์์๋ค์ ํ์๋ค๊ณผ ๊ณต์ ํ๊ณ , ์๋ก์ ์์
์ ์ค์ง์ ์ธ ๋์์ด ๋์๋ค๋ ์ ์ด ์ธ์ ๊น์๋ค. ๊ฐ์ ๋งก์ ์์ญ์ ๋ฌธ์ํํ๊ณ ๊ณต์ ํ๋ฉฐ ํ์ฉํ๋ ๋ฐฉ์์ด ์ฐ๋ฆฌ ํ์๊ฒ ์ ๋ง์๋ ๊ฒ ๊ฐ๋ค. ๊ฒ๋ค๊ฐ ํ์ด์ง ๊ฐ ๊ธฐ๋ฅ ๊ตฌ์กฐ๋ ์ ์ฌํด์, ํ ๋ฒ ์ ๋๋ก ๋ง๋ ์์ ์ ์๋ ํจ์๋ ์ฌ๋ฌ ํ
์คํธ์์ ๋ฐ๋ณต์ ์ผ๋ก ์ฌ์ฌ์ฉํ ์ ์์๋ค. ์ด๋ฌํ ๊ตฌ์กฐ ๋๋ถ์ ์ ์ฒด ์์
์๋๋ ์๊ฐ๋ณด๋ค ๋ ๋น ๋ฅด๊ฒ ์งํ๋ ์ ์์ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ ๋ค.
๊ทธ๋ฆฌ๊ณ ์ค๋ ์๋กญ๊ฒ ์๊ฒ ๋ ํ ํ๋! CLASS NAME ์
๋ ํฐ๋ฅผ ์ฌ์ฉํ ๋, ํด๋์ค๊ฐ ์ฌ๋ฌ ๊ฐ์ธ ์์๋ ์ ํํ๊ฒ ์ ํ๋์ง ์๋ ๊ฒฝ์ฐ๊ฐ ์๋ค๋ ์ ์ ๊ฒฝํํ๋ค. ๊ทธ๋์ ์ดํ์๋ CSS selector๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ ํํ๊ณ ์ ์ฐํ๋ค๋ ๊ฑธ ์๋กญ๊ฒ ๋ฐฐ์ ๋ค.
ํ์ฌ ๋ชฉํ๋ ํ์์ผ๊น์ง ์ฝ๋ ๊ตฌํ์ ๋ชจ๋ ๋ง๋ฌด๋ฆฌํ๊ณ , Jenkins ์ฐ๋๊น์ง ์๋ฃํ๋ ๊ฒ. ํ๋ฃจ ๋ง์ ๊ฐ๋ฅํ๊ฒ ์ง…?
๐ 3/31 - 7์ผ์ฐจ ํ๊ณ (๊ฐ์ธ ํผ๋ ์๋ํ ํ ์คํธ ๊ตฌํ ์๋ฃ)
์๋ฆฌ์ค Lab์ ๋์ฐฉํ์๋ง์ Jenkins ๊ด๋ จ ๊ณต์ง๊ฐ ๋์ฐฉํ๋ค. ๋๋๊ฒ๋ ์๋ฆฌ์ค ์ธก์์ ๊ณต์ ์๋ฒ๋ฅผ ์ ๊ณตํด์ค๋ค๋ ์์!
๋๋ถ์ ๋ ์ด์ ๋ก์ปฌ์์ ํฐ๋๋ง์ ์ํด ngrok์ ์ฐ์ง ์์๋ ๋ ๊ฒ ๊ฐ๋ค. ๊ทธ๋์ ngrok์ ์ธ ๋๋ง๋ค ์ฃผ์๊ฐ ๊ณ์ ๋ฐ๋์ด์ ๋ฒ๊ฑฐ๋ก์ ๋๋ฐ, ๊ณต์ ์๋ฒ ๋๋ถ์ ์ด ๋ฌธ์ ๋ ์ด๋ ์ ๋ ํด๊ฒฐ ๊ฐ๋ฅํ ๊ฒ ๊ฐ๋ค. ์ด์ Jenkins๋ฅผ ์ข ๋ ์์ ์ ์ผ๋ก ์ฌ์ฉํ ์ ์์ ๋ฏ!
๊ณต์ ์๋ฒ๋ฅผ ์ ๊ณต๋ฐ์๋ง์ ๋ช ๊ฐ์ง ์๋ฌธ์ด ๋ฐ๋ก ๋ ์ฌ๋๋ค.
- ๋ด๊ฐ ๋ง๋ Docker ์ด๋ฏธ์ง๋ฅผ ๊ทธ๋๋ก ์จ๋ ๋๋ ๊ฑธ๊น?
- ๊ณ ์ IP๋ผ์ ์ธ๋ถ ์ ์์ด ๋ ํธํด์ง ๊ฑด๊ฐ?
- ๊ทธ๋ ๋ค๋ฉด ๊ทธ๋ฅ ๋ก์ปฌ์์ ํ๋ ๋ฐฉ์ ๊ทธ๋๋ก ์งํํ๋ฉด ๋๋ ๊ฑด ์๋๊น?
๊ถ๊ธํ ๊ฑธ ๋ฐ๋ก GPT์๊ฒ ๋ฌผ์ด๋ดค๋๋ฐ, ์๊ฐ๋ณด๋ค ๋๋๊ฒ๋(?) ๋ด๊ฐ ๋ ์ฌ๋ฆฐ ์๋ฌธ์ด ์ ๋ถ ๋ง๋ ๋ง์ด์๋ค. ๊ฒฐ๋ก ์ ์ผ๋ก๋, ํ๊ฒฝ๋ง ๋ฐ๋์์ ๋ฟ, ๊ธฐ์กด์ ํ๋ ๋ฐฉ์ ๊ทธ๋๋ก ์งํํ๋ฉด ๋๋ค. ์๋ฒ ์์น๋ง ๋ฌ๋ผ์ก์ ๋ฟ, Docker๋ Jenkins๋ ์ค์ ๋ฐฉ์๋ ์ ๋ถ ๋์ผํ๊ณ , ์คํ๋ ค ๊ณ ์ IP ๋๋ถ์ ์ธ๋ถ ์ฐ๋์ด ๋ ์์ ์ ์ด๊ณ ์พ์ ํด์ง ๋๋์ด๋ค.
๋๋์ด.. ๊ฐ์ธ ํผ๋ ํ
์คํธ ํจ์ ๊ตฌํ ์๋ฃ! ์ค๋์ ํ์๋ค ๊ฐ์ ๋งก์ ํ์ด์ง ๊ตฌํ์ ์ง์คํ๋๋ผ, ๋ญ๊ฐ ์๋กญ๊ณ ์ธ์ ๊น์ ์ธ์ฌ์ดํธ๋ฅผ ์ป์๋ค๊ธฐ๋ณด๋ค๋, ์ ์ฒด ์์
์ ์ ๋ฆฌํ๊ณ ๋ํ
์ผ์ ๋ง๋ฌด๋ฆฌํ๋ ๋ฐ ์ด์ ์ด ๋ง์ถฐ์ง ํ๋ฃจ์๋ค.
๊ทธ๋๋ง ๊ธฐ์ต์ ๋จ๋ ๊ฑด...
- fixture์ ๋ค์ํ ์ต์ ์ ์ถ๊ฐํด๋ณด๋ ํ ์คํธ ์๋๊ฐ ํ ์ค์๋ค.
- implicitly_wait์ ์ค์ ํด๋๋ ์์๊ฐ ๋ฐ๋ก ์ ๋ณด์ฌ๋ n์ด๊น์ง ๊ธฐ๋ค๋ ค์ค์, time.sleep์ด๋ ๋ณํํ๋๊น ์๊พธ ๋ฐ์ํ๋ timeout์ด ์น ์ฌ๋ผ์ก๋ค.
์์ฃผ ์์ ์ค์ ํ๋๊ฐ ์ ์ฒด ์์ ์ฑ์ ๊ฝค ํฐ ์ฐจ์ด๋ฅผ ๋ง๋ค ์ ์๋ค๋ ๊ฑธ ๋ค์ ๋๊ผ๋ค.
๋จ์ ๊ธฐ๊ฐ ๋์ ๋ด๊ฐ ํ ์ผ ์ ๋ฆฌ
- ํ์๋ถ๋ค ์ฝ๋ ํจ๊ป ๋ฆฌ๋ทฐํ๊ธฐ
- Jenkins ์ฐ๋ ์ง์ค์ ์ผ๋ก ์๋ํด๋ณด๊ธฐ
- ๊ฐ assert์ log ์ถ๋ ฅ ๋ฃ๊ธฐ (๋ค๋ง ์ ์ฒด ํ ์คํธ ์ฑ๊ณต์ธ์ง, assert ํ๋ํ๋์ ์ฑ๊ณต์ธ์ง๋ ๊ตฌ๋ถํด์ ์ ์ ๊ฒ)
- ์์ด์ฝ ๊ธ๋จธ๋ฆฌ ๊ธฐํธ์ ์๋ [ ] ๊ฐ์ ๋๊ดํธ ์ ๊ฑฐ
- ์ฌ์ฉํ์ง ์๋ ํด๋ ์ ๋ฆฌ: config, testdata
- ๋ถํ์ํ ํจ์ ์ ๊ฑฐ: getVisibilityElement, isContainAllField (in myFeed class)
- ์๋ฏธ ์๋ ์ฃผ์ ์ ๊ฑฐ
๊ฒฐ๋ก ์ ์ผ๋ก๋, ์ง๊ธ ๋ด ์ญํ ์ ์ฝ๋ ์ ๋ฆฌ ๋ง๋ฌด๋ฆฌ + Jenkins ์ฐ๋ ์๋!
์๊ฐ์ด ์ข ๋จ๋๋ค๋ฉด ํ
์คํธ ์ฝ๋ ๋ฆฌํฉํ ๋ง์ด๋ ๊ฐ์์์ ๋ฐฐ์ด @pytest.mark.parametrize ๊ฐ์ ๊ธฐ๋ฅ๋ ํ๋์ฉ ์ ์ฉํด๋ณด๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
๐ 4/1 - 8์ผ์ฐจ ํ๊ณ (Jenkins ์ฐ๋ ์ฑ๊ณต / ํ ์คํธ ๋ก๊ทธ ์ถ๊ฐ ๋ฐ ๋ฆฌํฉํ ๋ง)
๋๋ ๋ด๊ฐ ๋งก์ ํ์ด์ง๋ค์ ์๋ํ ์ฝ๋ ๊ตฌํ์ ๋ชจ๋ ๋ง์น ์ํ์๊ธฐ ๋๋ฌธ์, ์ค๋์ ๋ค๋ฅธ ํ์๋ถ๋ค์ด ๊ฐ์ ๋งก์ ํ์ด์ง ๊ตฌํ์ ๊ณ์ ์งํํ๋ ๋์ ๋ณธ๊ฒฉ์ ์ผ๋ก Jenkins์ GitLab ์ฐ๋ ์์
์ ๋์ ํ๋ค.
์ฐ๋์ ์์, ์ฝ์น๋๊ป ๋ด๊ฐ ์๋ํ๋ ค๋ ๋ฐฉ์์ ๋ํด ๋จผ์ ์ฌ์ญค๋ดค๋๋ฐ, ์๋ฆฌ์ค ์ธก์์๋ hostname, user, password, public IP, ๊ทธ๋ฆฌ๊ณ ์ ์ ๋ฐฉ๋ฒ๊น์ง๋ง ์๋ด๋์๋์ง ํ์ธํ์๋๋ ํฌํธ ์ค์ ์ ๋ํ ๋ถ๋ถ๋ ํจ๊ป ์ฒดํฌํด๋ณด๋ ๊ฒ ์ข๊ฒ ๋ค๊ณ ์กฐ์ธํด์ฃผ์
จ๋ค. ๊ทธ๋์ ๋ฐ๋ก ๋งค๋์ ๋ถ๊ป ํฌํธ ๊ด๋ จ ๋ฌธ์๋ฅผ ๋๋ ธ๊ณ , ๊ทธ์ ๋ํ ๋ต๋ณ์ ๋ฐ์ ํฌํธ ์ ๋ณด๊น์ง ํฌํจํ ์ฐ๋์ ํ์ํ ๋ชจ๋ ์ ๋ณด๋ฅผ ํ๋ณดํ ์ ์์๋ค.
ํฌํธ
~> ํ๋์ ์ปดํจํฐ(์๋ฒ) ์์์ ์ฌ๋ฌ ๊ฐ์ ํ๋ก๊ทธ๋จ์ด ๋์์ ํต์ ํ ์ ์๋๋ก ํด์ฃผ๋ ‘๋ฌธ’ ์ญํ (์ฆ, IP ์ฃผ์๋ ‘๊ฑด๋ฌผ ์ฃผ์’, ํฌํธ ๋ฒํธ๋ ‘๊ทธ ์ฃผ์ ์์ ๋ฌธ ๋ฒํธ’)
~> ํฌํธ๊ฐ "์ด๋ ค ์๋ค'๋ ๊ฑด? ์๋ฒ์ ๋ฐฉํ๋ฒฝ(UFW, iptables ๋ฑ) ํน์ ํด๋ผ์ฐ๋ ๋ณด์ ๊ทธ๋ฃน์ด ํด๋น ํฌํธ๋ก์ ์ธ๋ถ ์ ์์ ํ์ฉํด์ค ์ํ๋ผ๋ ๋ป
์๋น์ค | IP ์ฃผ์ | ํฌํธ ๋ฒํธ | ์ ์ฒด ์ฃผ์ |
์น ์๋ฒ (Nginx) | 211.175.242.65 | 80 | http://211.175.242.65:80 |
Jenkins | 211.175.242.65 | 8080 | http://211.175.242.65:8080 |
DB (MySQL) | 211.175.242.65 | 3306 | 211.175.242.65:3306 |
~> ๊ฐ์ ์๋ฒ์์ ์ฌ๋ฌ ์๋น์ค๊ฐ ๋์ํ ๋, ์ด์ฒ๋ผ ๊ฐ์ IP๋ฅผ ๊ฐ์ง ์๋ฒ์์๋ ํฌํธ๊ฐ ๋ค๋ฅด๋ฉด ์๋ก ๋ค๋ฅธ ์๋น์ค์ ์ ์ ๊ฐ๋ฅ
๐ฅ ๋ณ๊ฒฝ ์ฌํญ
[ ๊ธฐ์กด ๋ฐฉ์ - Jenkins ์ปจํ ์ด๋ ์คํ (in VS Code ํฐ๋ฏธ๋) ]
docker run -d -p 8080:8080 -p 50000:50000 --name {์ปจํ ์ด๋ ์ด๋ฆ} {์ด๋ฏธ์ง ์ด๋ฆ}
> ๊ธฐ์กด์๋ ์ด๋ ๊ฒ ์คํํ๋๋ฐ, ์ด ๋ฐฉ์์ ๋ก์ปฌ ํ๊ฒฝ์์๋ง ๊ฐ๋ฅํ๋ ๋ฐฉ์์ด๋ค.
> ๊ธฐ์กด์๋ ๋ด ์ปดํจํฐ์์ ์ง์ ์ ์ํ๋ ๊ตฌ์กฐ์๊ธฐ ๋๋ฌธ์, 8080:8080์ฒ๋ผ ๋ด๋ถ ํฌํธ์ ์ธ๋ถ ํฌํธ๋ฅผ ๋์ผํ๊ฒ ์ฐ๊ฒฐํด๋ ๋ฌธ์ X
[ ๋ณ๊ฒฝ๋ ๋ฐฉ์ - Jenkins ์ปจํ ์ด๋ ์คํ (in VS Code ํฐ๋ฏธ๋) ]
docker run -d -p {์ธ๋ถ ํฌํธ}:{์ปจํ ์ด๋ ๋ด๋ถ ํฌํธ} -p 50000:50000 --name {์ปจํ ์ด๋ ์ด๋ฆ} {์ด๋ฏธ์ง ์ด๋ฆ}
> ํ์ง๋ง ๊ณต์ ์๋ฒ ํ๊ฒฝ์์๋ ์๋ฒ ์ธ๋ถ์์ ์ด๋ ค ์๋ ํฌํธ๊ฐ ์ ํด์ ธ ์๋ค.
> 8080์ Jenkins ๋ด๋ถ์์ ๊ณ ์ ๋ ํฌํธ์ด๊ธฐ ๋๋ฌธ์ ์ปจํ ์ด๋ ๋ด๋ถ ํฌํธ๋ ์ ๋ ๋ฐ๊พธ๋ฉด ์ ๋๋ค.
> ๋ฐ๊ฟ์ผ ํ๋ ๊ฑด ์ธ๋ถ ํฌํธ์ด๋ฉฐ, ์ด๋ ค ์๋ ํฌํธ๋ฅผ ์ฌ์ฉํ๋์ง ๊ผญ ํ์ธ์ด ํ์ํ๋ค.
๐ฅ ์๋ ๊ณผ์
[ ์ฐธ๊ณ ์ฌํญ ]
์๋ฆฌ์ค์์ ์ ๊ณตํ ์๋ฒ๋ Ubuntu ์๋ฒ์ด๋ฏ๋ก GUI ํ๊ฒฝ ์ ๊ณต X
> ๋ฐ๋ผ์ Docker๋ ํฐ๋ฏธ๋ ๋ช ๋ น์ด๋ฅผ ํตํด ์กฐ์
[ ๊ณต์ ์๋ฒ์ SSH๋ก ์ ์ (in cmd) ]
ssh {user}@{Public IP}
> ๊ณต์ ์๋ฒ์ ์๊ฒฉ ์ ์
[ ์ปจํ ์ด๋ ์คํ ์๋ ์ค, Docker ๋ฏธ์ค์น๋ก ์คํ ์คํจ ]

docker run -d -p 3000:8080 -p 50000 50000 team5:jenkins_custom
> ํด๋น ์๋ฒ์ Docker๊ฐ ์ค์น๋์ง ์์ ์ปจํ ์ด๋ ์คํ ์คํจ
[ docker ์ค์น (in cmd) ]
sudo apt update
> ๊ธฐ์กด ํจํค์ง ์ ๋ฐ์ดํธ
sudo apt install -y docker.io
> Docker ์ค์น
[ Dockerfile์ด ์๋ ํด๋ ์ ์ฒด๋ฅผ ์๋ฒ๋ก ๋ณต์ฌ (in VS Code ํฐ๋ฏธ๋) ]
์ Dockerfile์ด ๋ด๊ธด ํด๋๋ฅผ VS Code๋ก ์ด๊ธฐ

scp -r . {user}@{Public IP}:{์๋ฒ์์ ๋ณต์ฌ๋ ๊ฒฝ๋ก}
> ์ปค์คํ Jenkins ์ด๋ฏธ์ง ์์ฑ์ ์ํ Dockerfile์ด ๋ด๊ธด ํด๋๋ฅผ ์๋ฒ๋ก ๋ณต์ฌ
[ ๋ณต์ฌํ ํด๋๋ก ์ด๋ ํ ์ด๋ฏธ์ง ๋น๋ (in cmd) ]
ssh{user}@{Public IP}
> ๊ณต์ ์๋ฒ์ ์๊ฒฉ ์ ์

cd ~/jenkins-docker
> ๋ณต์ฌํ ํด๋๋ก ์ด๋
ls
> ํ์ผ์ด ์ ์์ ์ผ๋ก ๋ณต์ฌ๋์๋์ง ํ์ธ
sudo docker build -t {์ด๋ฏธ์ง ์ด๋ฆ} .
> ๊ด๋ฆฌ์ ๊ถํ์ผ๋ก Dockerfile ๊ธฐ๋ฐ ์ปค์คํ ์ด๋ฏธ์ง ์์ฑ
sudo docker images
> ๊ด๋ฆฌ์ ๊ถํ์ผ๋ก Dockerfile ๊ธฐ๋ฐ ์ปค์คํ ์ด๋ฏธ์ง ์์ฑ ํ์ธ
[ ์์ฑ๋ ์ด๋ฏธ์ง๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ปจํ ์ด๋ ์คํ (in cmd) ]
sudo docker run -d -p{์ธ๋ถ ํฌํธ}:{์ปจํ ์ด๋ ๋ด๋ถ ํฌํธ}-p 50000:50000 --name {์ปจํ ์ด๋ ์ด๋ฆ} {์ด๋ฏธ์ง ์ด๋ฆ}
> ๊ด๋ฆฌ์ ๊ถํ์ผ๋ก Jenkins์ฉ ์ปจํ ์ด๋ ์คํ ํ, ์ธ๋ถ์์ ์ ๊ทผ ๊ฐ๋ฅํ ์ํ๋ก ๊ตฌ๋
[ ์น ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด Jenkins ์ ์ ]
http://{Public IP}:{์ธ๋ถ ํฌํธ}
> ์น ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด Jenkins์ ์ ์
[ Jenkins ์ด๊ธฐ ๊ด๋ฆฌ์ ๋น๋ฐ๋ฒํธ ํ์ธ (in cmd) ]
sudo docker exec {์ปจํ
์ด๋ ์ด๋ฆ} cat /var/jenkins_home/secrets/initialAdminPassword
> ๊ด๋ฆฌ์ ๊ถํ์ผ๋ก ์ด๊ธฐ ๋น๋ฐ๋ฒํธ ์ถ๋ ฅ
[ ์ฐ๋ ์ฑ๊ณตํ์ง๋ง, ๋ฌธ์ ๋ฐ์ ]
"No such file or directory: 'credentials.json" ์ค๋ฅ ๋ฐ์
> ํ์ฌ ํ๋ก์ ํธ๋ credentials.json ํ์ผ ์์ ์ ์ฅ๋ id์ pw๋ฅผ ์ฝ์ด์ ๋ก๊ทธ์ธํ๋ ๊ตฌ์กฐ
> ์ด ํ์ผ์ ๋ฏผ๊ฐํ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๊ธฐ ๋๋ฌธ์ .gitignore์ ์ถ๊ฐํด๋์๊ณ , GitHub์๋ ์ฌ๋ผ๊ฐ์ง ์๋๋ก ๊ด๋ฆฌ
> Jenkins์์ ํด๋น ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ ๋๋ ์ด ํ์ผ์ด ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์, ํ์ผ์ ์ฐพ์ง ๋ชปํ๋ค๋ ์๋ฌ๊ฐ ๋ฐ์
> ์ด ๋ฌธ์ ๋ฅผ ์ฝ์น๋๊ป ์ง๋ฌธํด๋ณด๋, Jenkins ๋ด์ Credentials ๊ธฐ๋ฅ์ ํตํด ํด๊ฒฐํ ๊ฒ์ ์ถ์ฒ
[ ํ์ผ ๋ฑ๋ก ์ฑ๊ณตํ์ง๋ง, ๋ฌธ์ ๋ฐ์ ]
"cannot create credentials.json: Permission denied" ์ค๋ฅ ๋ฐ์
> Secret file๋ก credentials.json ํ์ผ์ ๋ฑ๋กํ์ ๋, ์ฒ์์ ์ ๋์ํ์ง๋ง, ์ด๋ ์๊ฐ๋ถํฐ ๊ถํ ์ค๋ฅ๊ฐ ๊ณ์ ๋ฐ์
> Secret text๋ก ๋ฐ๊ฟ๋ณด๊ธฐ๋ ํ๊ณ , pipeline ์ฝ๋๋ ์ฌ๋ฌ ๋ฒ ์์ ํด๋ดค์ง๋ง ๊ฒฐ๊ตญ ๊ณ์ ๊ฐ์ ๊ถํ ์๋ฌ๋ง ๋ฐ๋ณต
> ์๊ณ ๋ณด๋ Jenkins๊ฐ credentials ๋ฑ๋ก ์, ์ปจํ
์ด๋์ ์ํฌ์คํ์ด์ค ๋ด job ๋๋ ํ ๋ฆฌ์ ํด๋น ํ์ผ์ ์์ฑํ๋๋ฐ,
์ฒ์ ๋ง๋ค์ด์ก๋ ํ์ผ(credentials.json)์ด ์ด๋ฏธ ์กด์ฌํ ์ํ์์ ๊ฐ์ ์ด๋ฆ์ผ๋ก ํ์ผ์ ๋ค์ ๋ณต์ฌํ๊ฑฐ๋
์์ฑํ๋ ค๊ณ ํ๋ฉด, ๊ธฐ์กด ํ์ผ์ด ์ฝ๊ธฐ ์ ์ฉ(read-only) ์ด๊ธฐ ๋๋ฌธ์ ์ฐ๊ธฐ ๊ถํ์ด ์์ด์ ์๋ฌ๊ฐ ๋ฐ์ํ ๊ฒ
[ ๊ธฐ์กด ์ฝ๋ ]
pipeline {
agent any
environment {
CREDS_JSON = credentials('credentials-json')
}
stages {
stage('Run Tests') {
steps {
sh '''
cp "$CREDS_JSON" credentials.json
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
python3 -m pytest
'''
}
}
}
}
[ ์์ ๋ ์ฝ๋ ]
pipeline {
agent any
stages {
stage('Run Tests') {
steps {
sh '''
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
python3 -m pytest
'''
}
}
}
}
> ์ฆ, ์ฒ์ ์คํํ ๋๋ cp "$CREDS_JSON" credentials.json ์ฝ๋๋ฅผ ํตํด Secret file์ด ์ ์์ ์ผ๋ก ๋ณต์ฌ๋์๊ธฐ ๋๋ฌธ์ ์๋ฌด๋ฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์๋ค.
> ํ์ง๋ง ๊ฐ์ ์ฝ๋๋ฅผ ๋ฐ๋ณต ์คํํ๋ฉด์, ์ด๋ฏธ ์กด์ฌํ๋ credentials.json ํ์ผ์ ๋ค์ ๋ฎ์ด์ฐ๋ ค๋ค cp ๋ช ๋ น์ด์์ "Permission denied" ์๋ฌ๊ฐ ๋ฐ๋ณต์ ์ผ๋ก ๋ฐ์ํ๋ค.
> ๊ฒฐ๊ตญ cp "$CREDS_JSON" credentials.json ์ด ํ ์ค์ ์ ๊ฑฐํ๋ ๋ฐฉ์์ผ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ง๋ง, ์ด๋ป๊ฒ ๋ณด๋ฉด ์ผ๋งค์ ๊ฐ๊น์ด ํด๊ฒฐ์ด๋ค.
> ์๊ฐ ๋ถ์กฑ์ผ๋ก ๊ธํ๊ฒ ์ฒ๋ฆฌํ๊ธด ํ์ง๋ง, ๋์ค์ ์ฌ์ ๊ฐ ์๊ธด๋ค๋ฉด ๋ณด๋ค ์์ ์ ์ด๊ณ ๊น๋ํ ๋ฐฉ์์ผ๋ก ๋ค์ ํ๋ฒ ํด๊ฒฐ ๋ฐฉ์์ ์ฐพ์๋ณด๊ณ ์ถ๋ค.
๊ณต์ ์๋ฒ๋ฅผ ํตํ GitHub์ Jenkins ์ฐ๋์๋ ์ฑ๊ณตํ์ง๋ง, ๋ก์ปฌ์์ ์ ์์ ์ผ๋ก ํต๊ณผ๋๋ ํ
์คํธ๋ค์ด Jenkins์์๋ ์คํจ ํ๋ ํ์์ด ๋ฐ์ํ๋ค. ์ฒ์์๋ ๊ฐ์ ํ
์คํธ ์ฝ๋์ธ๋ฐ ์ Jenkins์์๋ง ์คํจํ๋์ง ์๋ฌธ์ด ๋ค์๋ค. ์คํผ์ค ์์ ์๊ฐ์ ์ฝ์น๋๊ป ์ง๋ฌธ์ ๋๋ ธ๊ณ , ์ฝ์น๋๋ ์ค๋ฌด์์ ์ข
์ข
๊ฒช๋ ๋ฌธ์ ๋ผ๊ณ ํ์
จ๋ค.
๊ทธ ์ด์ ๋ Jenkins ์์ฒด๊ฐ ์ด๋ ์ ๋ ๋ฆฌ์์ค๋ฅผ ์ ์ ํ๊ณ ์๊ธฐ ๋๋ฌธ์ด๋ผ๊ณ ์ค๋ช
ํด์ฃผ์
จ๋ค. ์ฆ, ๋ก์ปฌ์์ ํ
์คํธ๋ฅผ ๋๋ฆด ๋์ Jenkins ์๋ฒ์์ ๋๋ฆด ๋์ ํ๊ฒฝ์ด ์์ ํ ๋์ผํ ์ ์์ผ๋ฏ๋ก, ํ
์คํธ ์ฝ๋๊ฐ ์๋ฒ ํ๊ฒฝ์์๋ ์์ ์ ์ผ๋ก ๋์ํ ์ ์๋๋ก, ๋ ๋ง์ ๋๊ธฐ ์๊ฐ์ ๋ถ์ฌํ๊ฑฐ๋ ๊ฐ์ฅ ๋๋ฆฌ๊ฒ ๋ก๋ฉ๋๋ ์์๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฒ์ฆ ํ์ด๋ฐ์ ์กฐ์ ํ๊ฑฐ๋ ์คํจ ์ ์๋์ผ๋ก ์คํฌ๋ฆฐ์ท์ ์ฐ์ด ๋๋ฒ๊น
์ ํ์ฉํ๋ ๋ฐฉ์ ๋ฑ์ ์ฌ์ฉํด์ผ ํ๋ค๊ณ ํ์
จ๋ค.
๊ฒฐ๊ตญ Jenkins ํ๊ฒฝ์์์ ํ
์คํธ๋ ์๋๋ ์์ ์ฒ๋ฆฌ ๋ฐฉ์์ ์ฐจ์ด๋ฅผ ๊ฐ์ํด์ ์ข ๋ ์ ์ฐํ๊ณ ๋ฐฉ์ด์ ์ธ ๋ฐฉ์์ผ๋ก ์์ฑํด์ผ ํ๋ค๋ ์ ์ ๋ค์ ํ ๋ฒ ๋๋ผ๊ฒ ๋์๋ค. ์๊ฐ์ ์ด๋ฒ ์ค์ต์์๋ ์ด ๋ฌธ์ ๋ฅผ ์์ ํ ํด๊ฒฐํ์ง๋ ๋ชปํ์ง๋ง, ์์ผ๋ก๋ Jenkins์ ๊ฐ์ CI ํ๊ฒฝ์์๋ ์์ ์ ์ผ๋ก ๋์ํ ์ ์๋๋ก ํ
์คํธ ์ฝ๋ ์์ฒด๋ฅผ ๋ ๊ฒฌ๊ณ ํ๊ฒ ์ค๊ณํ ํ์์ฑ์ ๋๊ผ๋ค.
@pytest.mark.ys
def test_myFeed_001(createDriver):
try:
myfeed = myFeed(createDriver)
myfeed.goToPage("๊ฐ์ธ ํผ๋")
assert myfeed.getElement(myFeedLocators.MY_FEED_TXT)
assert myfeed.getElement(myFeedLocators.MY_PROFILE_CHANGE_SVG)
assert myfeed.getElement(myFeedLocators.MY_PROFILE_STAT_IMG)
assert myfeed.getElement(myFeedLocators.MY_MENU_PLUS_BTN)
assert myfeed.getElement(myFeedLocators.MY_EAT_SAME_MENU_BTN)
myfeed.logger.info("โถ๏ธ myfeed_001 - ๊ฐ์ธ ํผ๋ ํญ ์ ํ ์ UI ์์ ํ์ธ")
myfeed.getElement(myFeedLocators.MY_FEED_BACK_PAGE).click()
assert myfeed.getElement(myFeedLocators.HOME_TXT)
myfeed.logger.info("โถ๏ธ myfeed_002 - [๋ค๋ก๊ฐ๊ธฐ] ๋ฒํผ ํด๋ฆญ ์ ์ด์ ํ์ด์ง๋ก ์ด๋ ํ์ธ")
myfeed.logger.info(f"โ
{inspect.currentframe().f_code.co_name} ํต๊ณผ")
except Exception as e:
myfeed.logger.warning(f"โ {inspect.currentframe().f_code.co_name} : {e}")
raise
ํ์ฌ๋ ์ ์ฌํ ํ๋ฆ์ด๋ ๊ธฐ๋ฅ์ ๊ฐ๋ ํ
์คํธ ์ผ์ด์ค๋ค์ ๋ฌถ์ด, ํ๋์ ํ
์คํธ ํจ์ ์์์ ์ฌ๋ฌ TC๋ฅผ ๋์์ ๊ฒ์ฆํ๋ ๊ตฌ์กฐ๋ก ํ
์คํธ๋ฅผ ๊ตฌ์ฑํ๋ค. ๊ฐ ํ
์คํธ ํจ์ ์ด๋ฆ์ Google ์คํ๋ ๋์ํธ์ ์ ๋ฆฌํ ์๋ํ ํจ์ ID์ ๋์ผํ๊ฒ ์ค์ ํ์ผ๋ฉฐ, inspect ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํด ํ
์คํธ๊ฐ ์ฑ๊ณตํ๋ฉด ํด๋น ํจ์๋ช
์ด ์๋์ผ๋ก ๋ก๊ทธ์ ์ถ๋ ฅ๋๋๋ก ๊ตฌ์ฑํ๋ค. ๋๋ถ์ ํ
์คํธ ํจ์ ๋จ์๋ก๋ pass/fail ์ฌ๋ถ๋ฅผ ์ง๊ด์ ์ผ๋ก ํ์
ํ ์ ์์๋ค.
ํ์ง๋ง ๋ฌธ์ ๋, ํ๋์ ํ
์คํธ ํจ์์ ์ฌ๋ฌ TC๊ฐ ๋ฌถ์ฌ ์๋ค ๋ณด๋, ํจ์๊ฐ ์คํจํ์ ๋ ์ด๋ค TC์์ ์คํจํ๋์ง๊น์ง๋ ์ ์ ์์๋ค๋ ์ ์ด๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ์ด ํ๊ณ๋ฅผ ๋ณด์ํ๊ธฐ ์ํด, ํ
์คํธ ํจ์ ๋ด๋ถ์ ๊ฐ TC๋ง๋ค ๊ฐ๋ณ assert๋ฅผ ์์ฑํ๋ ๋ฐฉ์์ผ๋ก ๊ตฌ์ฑ์ ๋ณ๊ฒฝํ๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํน์ assert๊ฐ ์คํจํ์ ๋ ์ด๋ค TC๊ฐ ๋ฌธ์ ์๋์ง ๋ก๊ทธ๋ฅผ ํตํด ํ์ธํ ์ ์๊ณ , TC ๋จ์์ pass/fail ์ ๋ณด๋ฅผ ํ๋ณดํ๋ฉด์๋ ๊ธฐ์กด ํจ์ ๊ตฌ์กฐ๋ ์ ์งํ ์ ์์๋ค.
๐ 4/2 - 9์ผ์ฐจ ํ๊ณ (์์ฐ ์์ ์ ์ ๋ฐ ๋ฐํ ์ค๋น)
์ค๋์ ์ต์ข
์์ฐ ์์ ์ ์์ ์ํ ์์
์ ์งํํ๋ค. ๋จผ์ ํ
์คํธ ๋์ ๊ณผ์ ์ ์์์ผ๋ก ๋ด๊ธฐ ์ํด, time.sleep()์ ๊ณณ๊ณณ์ ์ฝ์
ํ์ฌ ์๋ง์ ๋ฌ ์ ์๋ ์ฌ์ ์๊ฐ์ ํ๋ณดํ๋ค. ๊ทธ ํ ๋ฐ๋์บ ์ ์ค์นํด ์ค์ ํ
์คํธ ๋์ ๊ณผ์ ์ ๋
นํํ๋ค. ๋
นํ๊ฐ ๋๋ ๋ค์๋, ๊ฐ์์ ์ฝ๋๋ฅผ ์ต์ข
์ ์ผ๋ก ์ ๋ฆฌํ ํ develop ๋ธ๋์น์ mergeํ๊ณ , ๋ชจ๋ ๋ณ๊ฒฝ ์ฌํญ์ main ๋ธ๋์น๋ก ์ต์ข
๋ฐ์ํ๋ค.
์์ ์ ์ ๊ฒฝํ์ด ์๋ ํ์๋ถ๊ป์ ํธ์ง๊ณผ ์์ ์ ์์ ๋งก์์ฃผ์
จ๊ณ , ์์ง ์ฝ๋๋ฅผ ๋ง๋ฌด๋ฆฌํ์ง ๋ชปํ ํ์๋ถ๋ค๊ป์๋ ๊ณ์ํด์ ๊ฐ์์ ๊ตฌํ ์์
์ ์ด์ด๋๊ฐ๋ค. ๋๋ ๊ฐ์ธ์ ์ผ๋ก ์ฝ๋ ์ ๋ฆฌ์ ๋ก๊ทธ ์บก์ฒ๊น์ง ๋ชจ๋ ์๋ฃํ์ผ๋ฉฐ, ์์ ๋
นํ๋ ๋ง๋ฌด๋ฆฌ๋ ์ํ์๋ค. ๊ทธ๋์ ๋ฐํ๋ฅผ ์ค๋นํ์๋ ํ์๋ถ์ ๋์, ํ์ํ ์๋ฃ๋ฅผ ์์งํ๊ณ ๋ฌธ์๋ฅผ ์ ๋ฆฌํ๋ ์์
์ ๋งก์์ผ๋ฉฐ, ํ์ํ ๋ด์ฉ์ ๋ฐ๋ก๋ฐ๋ก ๋ฌธ์๋ก ์์ฑํด ์ ๋ฌํ๋ฉด์ ๋๋ณธ ์์ฑ์๋ ์์ฐ์ค๋ฝ๊ฒ ๊ธฐ์ฌํ๊ฒ ๋์๋ค.
์ง๊ธ๊น์ง ๋ฐ๊ฒฌํ๋ ์ค๋ฅ๋ค์ ๋ชจ๋ Figma์ ์ ๋ฆฌํด๋์๊ณ , ๋ด๊ฐ ์ง์ ๊ฒช์๋ ์์
ํ๋ฆ๊ณผ ์ํ์ฐฉ์ค, ์ฃผ์ ๊ฒฐ์ ์ฌํญ๋ค๋ Figma์ ํ์๋ผ์ธ ํ์์ผ๋ก ์ ๋ฆฌํด ๊ณต์ ํ๋ค. ์ด ์๋ฃ๋ ๋ฐํ๋ฅผ ์ค๋นํ์๋ ํ์๋ถ๊ป์ ์ ์ฒด ํ๋ก์ ํธ ํ๋ฆ์ ๋น ๋ฅด๊ฒ ํ์
ํ๊ณ , ๋ฐํ ์๋ฃ๋ฅผ ๊ตฌ์ฑํ๋ ๋ฐ ํฐ ๋์์ด ๋์๋ค.
ํ์๋ถ๋ค๊ป์ ๊ฐ์ ์ฝ๋ ๋ง๋ฌด๋ฆฌ, ๋ก๊ทธ ์ถ๊ฐ, ์์ ์ดฌ์ ๋ฐ ๋ฐํ ์ค๋น ๋ฑ์ผ๋ก ๋ฐ์์ ์ํฉ์ด์ด์, ํด์ผ ํ ์ผ๋ค์ด ๋ค์ ํฉ์ด์ ธ ์๋ ๋๋์ด์๋ค. ๊ทธ๋์ ๋ด๊ฐ ๋ํ๋ก ์ ์ฒด ์์
ํญ๋ชฉ์ ์ ๋ฆฌํด To-Do ๋ฆฌ์คํธ ํํ๋ก ๊ณต์ ํ๊ณ , ์ด๋ฅผ ํตํด ๊ฐ์์ ์์
์งํ ์ํฉ๊ณผ ์์ผ๋ก ํด์ผ ํ ์ผ๊น์ง ํ๋์ ํ์
ํ ์ ์๋๋ก ๋์๋ค. ์ ๋ฆฌํ๋ ๊ณผ์ ์์ ๋ ์ญ์ ํ ์ ์ฒด์ ํ๋ฆ์ ๋ค์ ํ๋ฒ ์ ๊ฒํ ์ ์์๊ณ , ๊ทธ ๋๋ถ์ ์ดํ ์ผ์ ์กฐ์จ์ด๋ ์ง์์ด ํ์ํ ๋ถ๋ถ์ ๋ ๋น ๋ฅด๊ฒ ์บ์นํ ์ ์์๋ค.
Jenkins ์ค์ ๋ฐ ์ฐ๋ ๊ณผ์ , ๊ทธ๋ฆฌ๊ณ ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ์ ๋ํ ๋ฌธ์๋ ๋ด๊ฐ ์ง์ ์์ฑํด ํ์๋ค๊ณผ ๊ณต์ ํ๋ค. Jenkins์ GitLab ์ฐ๋์ ์ฒ์๋ถํฐ ๋๊น์ง ๋ด๊ฐ ์ง์ ์งํํ๋ ์์
์ด์๊ณ , ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ ์ญ์ ๊ตฌ์ฑ ๋ฐฉํฅ์ ์ฒ์๋ถํฐ ์ ๋ฆฌํ๋ฉฐ ์ฃผ๋์ ์ผ๋ก ์ก์๊ฐ๋ ๋ถ๋ถ์ด์๊ธฐ ๋๋ฌธ์, ํด๋น ๋ด์ฉ์ ๋ด๊ฐ ๊ฐ์ฅ ์ ํํ ์ค๋ช
ํ ์ ์๋ค๊ณ ํ๋จํด ๋ฌธ์๋ก ์ ๋ฆฌํ๊ฒ ๋์๋ค. ์ดํ ๋ฐํ๋ฅผ ์ค๋นํ์๋ ํ์๊ป์๋ ์ด ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํด ๊ด๋ จ ๋ด์ฉ์ ๋ฐํ ์๋ฃ์ ๋ฐ์ํ์
จ๊ณ , ํ์ํ ๋๋ง๋ค ์ถ๊ฐ ์๋ฃ๋ ํจ๊ป ์ ๋ฆฌํด ๊ณต์ ๋๋ ธ๋ค.
์คํผ์ค ์์ ์๊ฐ์๋ ์ฝ์น๋๊ป์ ์ด๋ ฅ์ ์์ฑ๊ณผ ๋ฉด์ ์ ๋ํด ์ค์ง์ ์ธ ์กฐ์ธ์ ํด์ฃผ์
จ๋ค.
์ด๋ ฅ์๋ฅผ ์์ฑํ ๋๋ ๋จ์ํ ๊ฒฝํ์ ๋์ดํ๋ ๊ฒ์ด ์๋๋ผ, ‘ํ์ → ๋ฌธ์ ์ ์ → ํด๊ฒฐ ๊ณผ์ → ํด๊ฒฐ ๊ฒฐ๊ณผ(์ฑ๊ณผ)’์ ํ๋ฆ์ ๊ฐ์ถ๋ ๊ฒ์ด ์ค์ํ๋ค๊ณ ํ์
จ๋ค. ์ด๋ ๊ฒ ์ ๋ฆฌํ๋ฉด ๋ด๊ฐ ์ด๋ค ๋ฌธ์ ์ํฉ์์ ์ด๋ค ์์ผ๋ก ๊ธฐ์ฌํ๋์ง, ๊ทธ๋ฆฌ๊ณ ์ด๋ค ๊ฒฐ๊ณผ๋ฅผ ์ด๋์ด๋๋์ง๊ฐ ๋ช
ํํ๊ฒ ๋๋ฌ๋๊ธฐ ๋๋ฌธ์ด๋ค.
๋ํ ์ฝ์น๋์ ๋ฉด์ ๊ณผ ๊ด๋ จํด์๋, ๋ชจ๋ ์ง๋ฌธ์๋ ๋ฐ๋์ ์๋๊ฐ ์๋ค๋ ์ ์ ๊ฐ์กฐํ์
จ๋ค. ์ง๋ฌธ์ ํ๋ฉด์ ์ธ ์๋ฏธ์๋ง ์ง์คํ๊ธฐ๋ณด๋ค, ๋ฉด์ ๊ด์ด ์ด ์ง๋ฌธ์ ํตํด ์ด๋ค ์ ์ ํ์ธํ๊ณ ์ถ์ด ํ๋์ง ์ญ์ผ๋ก ์๊ฐํด๋ณด๋ ์ฐ์ต์ด ํ์ํ๋ค๋ ๋ง์์ด ์ธ์ ๊น์๋ค.
๊ทธ๋ฆฌ๊ณ JD(์ฑ์ฉ ๊ณต๊ณ )๋ ๋จ์ํ ์ฝ๊ณ ๋๊ธฐ๋ ์ ๋ณด๊ฐ ์๋๋ผ, ๊ธฐ์
์ด ์ํ๋ ์ธ์ฌ์๊ณผ ์ญํ ์ด ๋ช
ํํ ๋๋ฌ๋๋ ๊ธฐ์ค์ด๋ฏ๋ก ๋ฐ๋์ ๋ถ์ํด์ผ ํ๋ค๊ณ ํ์
จ๋ค. JD๋ฅผ ๋ฐํ์ผ๋ก ๋ด๊ฐ ์ดํํ ๊ฒฝํ์ ์ ๋ณํ๊ณ , ๊ทธ์ ๋ง๊ฒ ์ด๋ ฅ์๋ ๋ฉด์ ๋ต๋ณ์ ๊ตฌ์ฑํ๋ ๊ฒ์ด ํจ๊ณผ์ ์ธ ์ค๋น ๋ฐฉ๋ฒ์ด๋ผ๊ณ ํ์
จ๋ค.
๐ 4/3 - 10์ผ์ฐจ ํ๊ณ (ํ๋ก์ ํธ ๋ฐํ)
์ด ๋ ์ ๋ด๊ฐ ๋งก์ TC ์ต์ข
๋ง๋ฌด๋ฆฌ ์์
์ ์งํํ๊ณ , ๋ฐ๊ฒฌ๋ ์ด์๋ Jira๋ฅผ ํ์ฉํด ๋ฒ๊ทธ ๋ฆฌํฌํธ๋ก ์ ๋ฆฌํด ๊ณต์ ํ๋ค. ๋ํ, PPT ์ ์๊ณผ ๋ฐํ ์ค๋น๋ฅผ ๋งก์ผ์ ๋ ํ์๋ถ๋ค์ด ์๋ ๋ฐ์ ์ํฉ์ด์ด์ ๊ทธ๋ถ๋ค์ ๋์ ํด ํ์ํ ๋ฌธ์ ์์ฑ ๋ฐ ์๋ฃ ๊ณต์ , ํ์ผ ์ ๋ฆฌ์ ์๋ฃ ์์ง ๋ฑ ๋ง๋ฌด๋ฆฌ ์์
๋ ํจ๊ป ์งํํ๋ค. ๊ทธ๋ ๊ฒ ํ๋ํ๋ ์ ๋ฆฌ๋ฅผ ํ๋ค ๋ณด๋ ์ด๋๋ง ๋ฐํ ์๊ฐ์ด ๊ฐ๊น์์ก๊ณ , ๋ฐํ ์๋ฃ ์ ์ถ ๋ง๊ฐ์ด ์คํ 3์์๋๋ฐ, ์ ๋ง ๊ฐ๋ฐ์ ์ฐจ์ด๋ก ์ ์ถ์ ์๋ฃํ ์ ์์์ ๋งํผ ๊ธ๋ฐํ๊ฒ ๋์๊ฐ๋ ํ๋ฃจ์๋ค.
์คํ 3์์ ๋ฐํ ์๋ฃ๋ฅผ ์ ์ถํ ๋ค, ๊ณง๋ฐ๋ก ๋ฐํ์ฉ PPT์ ๋๋ณธ์ ๋ํ ํผ๋๋ฐฑ์ ์ฃผ๊ณ ๋ฐ๋ค ๋ณด๋, ์ด๋๋ง ๋ฐํ ์์ ์๊ฐ์ธ ์คํ 5์๊ฐ ๋์ด ์์๋ค. ์ฐ๋ฆฌ ์กฐ๋ ์ค๋ ์คํ 12์๋ถํฐ ๋ฐํ๊ฐ ๋๋๋ ์คํ 7์๊น์ง ๋จ ํ ๋ผ๋ ๋จน์ง ๋ชปํ๋ค๋ ์ฌํ ์ฌ์ค.. ์ค๊ฐ์ ๋๋ฌด ๋ฐฐ๊ฐ ๊ณ ํ์ ์๋์์น๋ฅผ ์ฌ ์ค๊ธด ํ์ง๋ง, ๋จน์ง๋ ๋ชปํ๊ณ ์คํฐ๋๋ฃธ ๊ฒฝ๊ณ 1ํ๋ง ํ๋ํด๋ฒ๋ ธ๊ณ , ๊ทธ ์๋์์น๋ ์์ง๋ ๋ด ๋์ฅ๊ณ ์์ ๊ทธ๋๋ก ์๋ค..
์ฌ์ค ์ค๋ ๊ณต์์ ์ธ ์์
์ข
๋ฃ ์๊ฐ์ ์คํ 11์์์ง๋ง, ํ๋ก์ ํธ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ๋ง๋ฌด๋ฆฌ๋๊ธฐ๋ ํ๊ณ , ์คํ๋ผ์ธ ์กฐ์ด๊ธฐ๋ ํด์ ํ๊ณ ๋ ์์ฐ์ค๋ฝ๊ฒ ์ ์๋ฆฌ์์ ์ด์ด์ง๊ฒ ๋์๋ค ใ
ใ
์กฐํด ์ฒ๋ฆฌ 1ํ์ ๋๋ ๊ด์ฐฎ์์ ์์งํ..
๐ฏ 1์ฐจ ํ๋ก์ ํธ ์ต์ข ํ๊ณ
โ ํจ๊ป ๋ง๋ , ํจ๊ป ์ฑ์ฅํ ์ดํ
์ด๋ฒ ํ๋ก์ ํธ์์ ๊ฐ์ฅ ์ธ์ ๊น์๋ ์ ์, ํ ๋ถ์๊ธฐ์ ํ์ ์ด ๊ฒฐ๊ณผ์ ๋ฏธ์น๋ ์ํฅ์ด ์ ๋ง ํฌ๋ค๋ ์ฌ์ค์ด์๋ค.
์ค๋ฌด ๊ฒฝํ์ด ์๊ฑฐ๋ ์ฝ๋ ์์ฑ์ ์ต์ํ์ง ์์ ํ์๋ค๋ ์์์ง๋ง, ๊ฐ์์ ๊ฐ์ ์ ์ด๋ ค ์์ฐ์ค๋ฝ๊ฒ ๋ณด์ํ๊ณ , ์๋ก ๋ฐฐ์ฐ๋ฉฐ ํจ๊ป ์ด๋์ด์ค ๋๋ถ์ ๋จ ํ ๋ช ์ ๋์ค ์์ด ๋๊น์ง ํจ๊ป ์์ฃผํ ์ ์์๋ค. ์ญํ ๋ถ๋ด๋ ์์ฐ์ค๋ฝ๊ณ ํจ์จ์ ์ผ๋ก ์ด๋ค์ก์ผ๋ฉฐ, ๋๋ ํนํ TC ์์ฑ ๋จ๊ณ์์ ํ์๋ค์๊ฒ ๋ง์ ๋์์ ๋ฐ์๊ณ , ๋ฐ๋๋ก ์ฝ๋ ๊ตฌํ์ด๋ Jenkins ์ฐ๋ ๊ฐ์ ๊ธฐ์ ์ ์ธ ๋ถ๋ถ์์๋ ๋ด๊ฐ ๋จผ์ ๋์์ ๊ธฐ์ฌํ ์ ์์๋ค.
๋ฌด์๋ณด๋ค ์ด๋งํผ ์ข์ ํ ๋ถ์๊ธฐ ๋๋ถ์ ์๊ฒฌ์ ์์ ๋กญ๊ฒ ์ ์ํ ์ ์๋ ํ๊ฒฝ์ด ๋ง๋ค์ด์ก๊ณ , ๊ทธ ๊ณผ์ ์์ ์์ฐ์ค๋ฝ๊ฒ ๊ธฐ๋ฅ ๋ช ์ธ์๋ฅผ ๊ธฐ์ค์ผ๋ก ์์ฑํ๋ TC๋ฅผ ํ๋ฉด(Tab) ๋จ์๋ก ์ ๋ฆฌํ๋ ๋ฐฉ์์ผ๋ก ์ ํํ ์ ์์๋ค. ๋ํ, goToPage ํจ์๋ Locator ํ์ผ ๋ถ๋ฆฌ์ ๊ฐ์ ์์ด๋์ด๋ ์์ ๋กญ๊ฒ ์ค๊ฐ ์ ์์๊ณ , ์ด๋ฌํ ๊ตฌ์กฐ ๊ฐ์ ๋ค์ ์๋ํ ์ฝ๋์ ์์ฑ๋์ ์ ์ง๋ณด์์ฑ์ ๋์ด๋ ๋ฐ ํฐ ๊ธฐ์ฌ๋ฅผ ํ๋ค.
์ ์ฒด์ ์ธ ํ๋ฆ ์์์ ๊ฐ๋์ ํ์๋ค์ ์ง์ค๋ ฅ์ด ํํธ๋ฌ์ง๊ฑฐ๋ ๋ฐฉํฅ์ด ํ๋ค๋ฆฌ๋ ์๊ฐ๋ค๋ ์์๋ค. ๊ทธ๋ด ๋ ๋๋ ๋ถ์๊ธฐ๋ฅผ ๋ค์ก๊ธฐ ์ํด ์กฐ์ฌ์ค๋ฝ๊ฒ ์ด์๋ฆฌ๋ฅผ ํ๊ธฐ๋ ํ๊ณ , ํ๋ฆ์ ๋ฒ์ด๋์ง ์๋๋ก ์ค์ฌ์ ๋ค์ ์ก๋ ์ญํ ์ ํ๋ ค ๋ ธ๋ ฅํ๋ค. ๋จ์ํ ์ํด๋ณด์๋ ๋ง์๋ง์ผ๋ก๋ ๋ถ์กฑํ๋ค๋ ๊ฑธ ๋๊ตฌ๋ณด๋ค ์ ์๊ณ ์์๊ธฐ ๋๋ฌธ์, ๋ง์ง๋ง๊น์ง ์ฐ๋ฆฌ ํ์ด ํ๋ค๋ฆฌ์ง ์๊ณ ๋๊น์ง ๊ฐ ์ ์๋๋ก ์ด๋์ด๊ฐ๊ณ ์ถ์๋ค. ๊ฒฐ๊ตญ ๊ทธ๋ฐ ๊ณผ์ ์ ๊ฑฐ์น๋ฉฐ, ์ฐ๋ฆฌ ํ์ ๋๊น์ง ์ง์ค๋ ฅ์ ์ ์งํ ์ ์์๊ณ , ์ค์ค๋ก๋ ํ ์ ์ฒด๊ฐ ์ ๋ง๋ฌด๋ฆฌ๋ ์ ์๋๋ก ์กฐ๊ธ์ด๋๋ง ๋ฐฉํฅ์ ์ก์์ฃผ๋ ์ญํ ์ ํ๋ค๋ ์ ์ด ๋ฟ๋ฏํ๊ฒ ๋๊ปด์ก๋ค.
๋งค์ผ๋งค์ผ ์ ์ ์์ด ๋ฐ๋นด์ง๋ง, ํ์๋ถ๋ค ๋๋ถ์ ๊ทธ๋งํผ ๋ง์ด ์์๋ ์๊ฐ๋ค๋ ๋ง์๊ณ , ์ ๋ง ์ค๋๋ง์ ์ฌ๋ ๊ด๋ จํ ์คํธ๋ ์ค๋ ํฌ๊ฒ ์์๋ ๊ฒ ๊ฐ๊ณ , ๋๋ฆ ์ฆ๊ฒ๊ฒ ์ผํ ์ ์์๋ ์กฐํฉ์ด์๋ ๊ฒ ๊ฐ๋ค. ๊ฒฐ๊ณผ๊ฐ ์ด๋ป๋ , ์ด๋ฒ ํ ํ๋ก์ ํธ๋ฅผ ํตํด ์ ๋ง ๋ง์ด ๋ฐฐ์ฐ๊ณ ์ฑ์ฅํ๋ค๋ ์ฌ์ค๋งํผ์ ๋ถ๋ช ํ๋ค. ์งง์ง๋ง ๊ฐ๋ ฌํ๋ 10์ผ์ด์๋ค!
โ ํ ์คํธ ์ผ์ด์ค ์์ฑ๊ณผ ์๋ํ ๊ตฌํ์์์ ๊ณ ๋ฏผ๋ค
์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ํตํด ์๋๋ฆฌ์ค ์ค์ฌ์ผ๋ก ํ๋ฆ์ ๊ณ ๋ คํ TC ์์ฑ์ ์ค์์ฑ์ ํ์คํ ๋ฐฐ์ธ ์ ์์๋ค.
์ด๋ฒ์๋ TC๋ฅผ ์ง๋์น๊ฒ ์ธ์ธํ๊ฒ ๋๋ ๋ถ๋ถ์ด ์์๊ณ , ๊ทธ๋ก ์ธํด ์๋ํ ์ฝ๋ ์์ฑ ์ ํ๋ฆ์ด ๋ถ์ ๋๊ณ ๋ฐ๋ณต์ด ๋ง์์ ธ ์คํ๋ ค ๋นํจ์จ์ ์ด์๋ค๋ ์ ๋ ์ค๊ฐํ๋ค. ๊ทธ๋์ ๋ค์์๋ ์๋๋ฆฌ์ค ์ค์ฌ + ๋ชฉ์ ๋จ์ + ๋ช
ํํ ํ
์คํธ ์
๋ ฅ๊ฐ์ ๊ธฐ์ค์ผ๋ก, ์๋ํ์ ๋ ์ ํฉํ TC ์์ฑ ๋ฐฉ์์ผ๋ก ๊ฐ์ ํด๋ณด๊ณ ์ถ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
๊ทธ๋ ์ง๋ง ์ฐ๋ฆฌ ํ์ ์ด ์ธ์ธํ๊ฒ ๋๋ TC๋ค์ ํ๋์ ํ ์คํธ ํจ์ ์์์ ๋์์ ๊ฒ์ฆํ๋ ๊ฒ์ด ํจ๊ณผ์ ์ธ ์ผ์ด์ค๋ค๋ก ๋ฌถ์ด, ํ ์คํธ ํจ์ ID๋ฅผ ๋ถ์ฌํด ์ฒด๊ณ์ ์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์, ์ ํ์ฑ๊ณผ ํจ์จ์ฑ์ด๋ผ๋ ๋ ๋ง๋ฆฌ ํ ๋ผ๋ฅผ ๋ชจ๋ ์ก์ ์ ์์๋ค๊ณ ์๊ฐํ๋ค. ์ด๋ฌํ ์ ๊ทผ์ ์๋ํ ์ฝ๋๋ฅผ ์์ฑํด๊ฐ๋ฉฐ ์์ฐ์ค๋ฝ๊ฒ ํ๊ณ๋ฅผ ์ฒด๊ฐํ๊ณ , ๊ทธ๋๊ทธ๋ ์ ์ฐํ๊ฒ ๋์ฒํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฅํ๋ ๊ฒฐ๊ณผ์๋ค๊ณ ๋๋๋ค.
โ Jenkins ์ฐ๋๊ณผ ์ค๋ฌด ๊ฐ๊ฐ
Jenkins ์ฐ๋์ ๋ด๊ฐ ์ฒ์๋ถํฐ ๋๊น์ง ์ง์ ๋งก์ ์งํํ ์์ ์ผ๋ก, ์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ํตํด CI ํ๊ฒฝ์ ์ค์ค๋ก ๊ตฌ์ถํด๋ณด๋ ๊ฒฝํ์ ํ ์ ์์๋ค. ํผ์์ ํด๋ด์ผ ํ๋ค๋ ์ฑ ์๊ฐ๊ณผ ๋ถ๋ด๊ฐ ์์์, ํ๋ฃจ์ 10์๊ฐ ๋๊ฒ, ์ดํ ๋๋๋ก ์ฝ์งํ๋ฉฐ ๋ ธ๋ ฅํ ๋์ ๊ฒฐ๊ตญ ์ฐ๋์ ์ฑ๊ณตํ๊ณ , ๊ทธ ์๊ฐ์ ๋ฟ๋ฏํจ์ ์ ๋ง ์ปธ๋ค.
์ด ๊ณผ์ ์์ Docker๋ฅผ ํ์ฉํ Jenkins ์ด๋ฏธ์ง ๋น๋์ ์ปจํ ์ด๋ ์์ฑ, ํ๋ก์ ํธ์ ๋ง์ถ ํ๊ฒฝ ์ธํ , ๊ทธ๋ฆฌ๊ณ ํ์๋ค์๊ฒ ๋์ผํ ํ๊ฒฝ์ ๋น ๋ฅด๊ฒ ์ ์ฉํ๊ธฐ ์ํ Dockerfile ์ ์๊น์ง ์ ๋ง ๋ง์ ์ค์ ๊ฒฝํ์ ํด๋ณผ ์ ์์๋ค. ๊ทธ๋งํผ ๋ฐฐ์ด ๊ฒ๋ ๊ฐ์ฅ ๋ง์๋ ํํธ์๊ณ , ๋์์ ๊ฐ์ฅ ๋๋ฅผ ๊ดด๋กญํ๋ ํํธ์ด๊ธฐ๋ ํ๋ค.
๋ง์ด ํ๋ค๊ธด ํ์ง๋ง, ๊ทธ ๊ณผ์ ์ ํตํด ์ด๋ก ์์ ๋ณด๋ค ํจ์ฌ ๊ฐ๋ ฅํ ์ค์ ๊ฐ๊ฐ์ ์ป๊ฒ ๋์๋ค๊ณ ๋๋๋ค.
โ ์๋ํ ์ฝ๋์ ๊ตฌ์กฐ ์ค๊ณ
์๋ํ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด์ ๊ฐ์ฅ ํฌ๊ฒ ๋๋ ์ ์, “์๋ฌด๋ฆฌ ์๋ํ๋ฅผ ํ๋๋ผ๋ ๋ฐ๋ณต์ ์กด์ฌํ๋ค”๋ ํ์ค์ด์๋ค.
๋ฐ๋ณต์ ์ต๋ํ ์ค์ด๊ธฐ ์ํด
- ์ค๋ณต ๋์์ goToPage() ํจ์๋ก ๋ถ๋ฆฌํ๊ณ ,
- ํ์ด์ง๋ณ๋ก locator ํ์ผ์ ๋ฐ๋ก ๊ด๋ฆฌํ์ผ๋ฉฐ,
- ๋ฐ๋ณต๋๋ ์ฝ๋ ํ๋ฆ์ ํจ์ํํ์ฌ ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๊ณ ์ ํ๋ค.
์ด๋ฌํ ๊ตฌ์กฐ๋ ์ค์ ๋ก ์ ์ง๋ณด์์ฑ๊ณผ ํ์
ํจ์จ์ ๋์ด๋ ๋ฐ ๊ฝค ํจ๊ณผ์ ์ด์๋ค.
๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ , ์ฌ์ ํ ๋ฐ๋ณต์ ์ธ ๊ตฌ์กฐ๋ก ํ๋ฌ๊ฐ๋ ํ
์คํธ ์ฝ๋๋ฅผ ๋ณด๋ฉด์ “์๋ํ ์ญ์ ๋ฐ๋ณต์ ์ด๋ค ๋ณด๋ ์ค๋ฌด์์ ํํ๊ฐ ์ค๊ธฐ๋ ํ๋ค”๋ ์คํผ์ค ์์ ์ฝ์น๋์ ๋ง์์ด ์ ๋ง ๊ณต๊ฐ๋์๋ค. ์๋ฌด๋ฆฌ ์๋ํ๋ฅผ ํด๋ ๊ฒฐ๊ตญ ๋ณํ์ ๋ฐ๋ผ ์ ์ง๋ณด์๋ ํ์์ด๊ณ , "์ด๋ป๊ฒ ํ๋ฉด ๋ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์๊น?"๋ผ๋ ๊ณ ๋ฏผ์ ์์ผ๋ก๋ ๊ณ์ ๋ฐ๋ณต๋ ์๋ฐ์ ์๋ ์์ ์ฒ๋ผ ๋๊ปด์ก๋ค.
โ ํ์ํฌ, ํต์ผ์ฑ, ๊ทธ๋ฆฌ๊ณ ์ง์ง ์ค๋ฌด ๊ฐ๊ฐ
ํ๋ก์ ํธ ํ๋ฐ๋ถ๋ก ๊ฐ์๋ก ์ผ์ ์ด ์ด๋ฐํด์ก๊ณ , ์๋ฃ ์ ๋ฆฌ, ๋ฐํ ์ค๋น, ์์ ์ดฌ์ ๋ฑ ํด์ผ ํ ์ผ๋ค์ด ํ๊บผ๋ฒ์ ๋ชฐ๋ฆฌ๋ฉด์ ์ ๋ฐ์ ์ผ๋ก ๋ค์ ๊ธ๋ฐํ ๋ถ์๊ธฐ๊ฐ ์์๋ ์ ์ ์์ฌ์์ผ๋ก ๋จ๋๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ , ๋ชจ๋๊ฐ ์๊ธฐ ์ญํ ์ ๋์ง ์๊ณ ๋๊น์ง ์์ฃผํ๋ค๋ ์ ์ ์ ๋ง ์๋์ค๋ฌ์ ๋ค.
ํนํ ์ด๋ฒ ํ๋ก์ ํธ์์๋ Git์ ํ์ฉํ ํ์ ๋ฐฉ์์ ๋ํด ์ค์ง์ ์ผ๋ก ๋ง์ด ๊ฒฝํํ ์ ์์๋ค. ๊ฐ ๊ธฐ๋ฅ์ ๊ฐ๋ณ ๋ธ๋์น๋ก ๋ถ๋ฆฌํด์ ์์ ํ๊ณ , PR(Merge Request)์ ํตํด ๋ณ๊ฒฝ ์ฌํญ์ ๊ณต์ ํ๊ณ ๋ฆฌ๋ทฐํ๋ฉฐ ์ถฉ๋์ ๋ฐฉ์งํ๋ ํ๋ฆ์ ๋ฐ๋ณต์ ์ผ๋ก ์ตํ๋ค. ๋ํ ์ปค๋ฐ ์์๋ [ADD], [UPDATE], [DELETE] ๋ฑ Prefix๋ฅผ ๋ถ์ฌ ์์ ๋ด์ญ์ ๋ช ํํ๊ฒ ๊ตฌ๋ถํ๊ณ , ๊ฐ๋จํ ๋ณ๊ฒฝ์ด๋ผ๋ ์๋ฏธ ์๋ ์ปค๋ฐ ๋ฉ์์ง๋ฅผ ์์ฑํ๋ ค๋ ์ต๊ด์ ์ตํ๊ฒ ๋์๋ค. Git ๋ช ๋ น์ด๋ฟ ์๋๋ผ GitHub Desktop, Sourcetree ๋ฑ ๋ค์ํ ๋๊ตฌ๋ค์ ์ค์ ์์ ์ฌ์ฉํด๋ดค๊ณ , ์ค์ ํ์ ์ํฉ์์ ๋ธ๋์น ์ ๋ต๊ณผ ๋ฒ์ ๊ด๋ฆฌ๊ฐ ์ผ๋ง๋ ์ค์ํ์ง ์ฒด๊ฐํ ์ ์์๋ค.
๊ทธ๋ฆฌ๊ณ ๋ฌด์๋ณด๋ค, ์ด๋ฒ ํ๋ก์ ํธ๋ฅผ ํตํด ์ฝ๋ ํต์ผ์ฑ๊ณผ ์ผ๊ด์ฑ์ ์ค์์ฑ๋ ๊น์ด ๊นจ๋ฌ์๋ค. ์ด๋ฐ์ ๋ณ์๋ช , ํจ์๋ช , ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ ๋ฑ์ ๋ํ ๊ธฐ์ค์ ๋ช ํํ ์ ํ๊ณ , ๊ทธ ๊ธฐ์ค์ ๋๊น์ง ์ ์งํ๋ ๊ฒ์ด ํ์ ํจ์จ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ๋์ด๋ ํต์ฌ ์์๋ผ๋ ์ ์ ์ง์ ๊ฒฝํํ๋ค. ๋ฌผ๋ก ์ค์ ์์ ๊ณผ์ ์์๋ ์ด์์ด ์ฌ๋ฌ ๋ฒ ๋ฐ๋๊ธฐ๋ ํ๊ณ , ๊ทธ๋ด ๋๋ง๋ค ๋ ๋์ ๋ฐฉํฅ์ด ๋ณด์ด๋ฉด ๊ณผ๊ฐํ ์์ ํ๊ณ ์ ์ฐํ๊ฒ ๋ฐ์๋ค์ด๋ ํ๋๋ ์ค์ํ๋ค๋ ๊ฑธ ํจ๊ป ๋๊ผ๋ค.