๐ก ์ด ๊ธ์์ ํ ์คํธํด ๋ณผ ๋ด์ฉ์ nginx + jenkins + springboot + github๋ฅผ ์ฌ์ฉํ์ฌ ํ๋ก์ ํธ ์๋ฒ์ ๋ฐฐํฌ ์๋ํ ๋ฐ ๋ฌด์ค๋จ ๋ฐฐํฌ๋ฅผ ๋ก์ปฌ ํ๊ฒฝ์ ๊ตฌํํ๋ ๊ฒ์ด๋ค.
๐ ์ ํจ์ค ์ค์น

- ๋ก์ปฌ์์ ์ ํจ์ค๋ฅผ ์ค์นํ๋ ๋ฐฉ๋ฒ์ ๊ฐ๋จํ๋ค.
- https://www.jenkins.io/
- ์ ๋งํฌ์ ์ ์ํ์ฌ ๋ค์ด๋ก๋๋ฅผ ํด๋ฆญํ๋ค.

- ๊ทธ๋ผ ์ ํจ์ค๋ฅผ ๋ค์ด๋ก๋ ํ ์ ์๋ ํ์ด์ง๊ฐ ๋์ค๋๋ฐ ๊ฐ ์ด์์ฒด์ ๋ ์ปจํ ์ด๋ ํ๊ฒฝ์์ ๋ง๋ ๊ฑธ ํด๋ฆญํ๋ฉด ๋ค์ด๋ก๋ํ๋ ๋ฐฉ๋ฒ์ด ๋์จ๋ค.
- MAC์ ๊ธฐ์ค์ผ๋ก ์ค๋ช ํ๋ฉด macOS๋ฅผ ํด๋ฆญํ๋ค.

- ๊ทธ๋ผ ์ด๋ ๊ฒ Homebrew๋ก ๋ค์ด๋ก๋ํ๋ ๋ฐฉ๋ฒ์ด ๋์จ๋ค.
brew install jenkins
brew services start jenkins
- ์ฒ์ ์ค์น๋ผ๋ฉด ์ ๋ ๋ช ๋ น์ด๋ก ๊ฐ๋จํ ์ค์นํ๊ณ ์คํ์ํฌ ์ ์๋ค.
https://suzuworld.tistory.com/415
๋ก์ปฌ ํ๊ฒฝ์์ ๋์ปค ์ ํจ์ค(Jenkins) ์ปจํ ์ด๋๋ก ๊นํ๋ธ ๋ ํ์งํ ๋ฆฌ ํด๋ก ํ ์คํธํ๊ธฐ(with Ngrok)
๐ก ๋ค์ด๊ฐ๊ธฐ ์ ์ ๋์ปค์ jenkins ๊ณต์์ด๋ฏธ์ง๋ Deprecated ๋์๋ค. ๋์ ๊ฒฝ์ฐ ์๋ฐ 11 ๋ฒ์ ์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ lts-jdk 11 ๋ฒ์ ์ ์ฌ์ฉํ๋ค. LTS(Long Term Support)๋ ์ฅ๊ธฐ ์ง์ ๋ฒ์ ์ด๋ ์๋ฏธ๋ก, ์ผ๋ฐ์ ์ธ ๊ฒฝ
suzuworld.tistory.com
- ์ ํจ์ค๋ฅผ ์คํํ๊ณ Github ๋ ํ์งํ ๋ฆฌ์ ์ ์ฅ๋ ํ๋ก์ ํธ ํ์ผ์ ์ ํจ์ค ์ํฌ์คํ์ด์ค๋ก ํด๋ก ํ๋ ๋ฐฉ๋ฒ์ ์ ๋งํฌ์ ๋งค์ฐ ์์ธํ ์ค๋ช
ํด ๋์๋ค.
- ์ฌ๊ธฐ์์๋ ์ ํจ์ค ์ค์น ํ ์คํ๋ง ๋ถํธ ์๋ฒ ์ธํ ๊ณผ ์ ์คํฌ๋ฆฝํธ & ์ ํจ์ค ํ์ผ ์์ฑ์ ๋ฉ์ธ์ผ๋ก ๋ค๋ฃฌ๋ค.
- ๋ง์ฝ ์ ํจ์ค๊ฐ ์์ ํ ์ฒ์์ด๋ผ๋ฉด ๊ผญ ํด๋ก ๊น์ง์ ํ ์คํธ๋ฅผ ๋ฐ๋ผ ํด ๋ณด๋ ๊ฒ์ ์ถ์ฒํ๋ค.
- ์ ๋งํฌ์ ๊ธ์ ๋์ปค ์ปจํ
์ด๋ ๊ธฐ์ค์ผ๋ก ์ค๋ช
ํ๊ณ ์์ผ๋ ๋ก์ปฌ ์ ํจ์ค ์ค์น์ ๋ค๋ฅธ ๋ถ๋ถ์ ๋ํด ์ด์ผ๊ธฐํ๊ฒ ๋ค.
- ๋์ปค์ ๊ฒฝ์ฐ ์ ํจ์ค ํฌํธ๋ฅผ <docker run> ๋ช ๋ น์ด๋ก ์ฝ๊ฒ ๋ณ๊ฒฝ์ด ๊ฐ๋ฅํ์ง๋ง, mac์ ์ง์ ์ค์นํ๋ ๊ฒฝ์ฐ์๋ ์ด๊ธฐ ํฌํธ๊ฐ 8080์ผ๋ก ์คํ๋๋ค.
- macOS ๊ธฐ์ค์ผ๋ก ์ ํจ์ค ํฌํธ๋ฅผ ๋ณ๊ฒฝํ๋ ๋ฐฉ๋ฒ ๋ฑ ๋ก์ปฌ์ ์ ํจ์ค๋ฅผ ์ค์นํ ๊ฒฝ์ฐ์๋ ๋ฐ๋ผํ ์ ์๊ฒ ์ค๋ช ์ ์ถ๊ฐํด ๋์์ผ๋ ์ ๋งํฌ์ ๊ธ์ ๋ฐ๋ผ Jenkins ๊ธฐ๋ณธ ์ค์ ์ ๋๋ด๊ณ ๋์์ค์.
โ ์ ํด๋ก ํ ์คํธ๋ ๋์ปค ์ปจํ ์ด๋๋ก ํ๊ณ ๋ฐฐํฌ ํ ์คํธ๋ ๋ก์ปฌ PC์ ์ ํจ์ค๋ก ํ์๋์?
- ์๋๋ ์ ํจ์ค ์ปจํ
์ด๋๋ก ํ๊ณ ์ถ์์ผ๋, ํน์ ์ธ๋ถ ์๋ฒ์ ๋ฐฐํฌํ๋ ๊ฒ์ด ์๋ 100%ํ๋์ ๋ก์ปฌ ์๋ฒ์ ๋ฐฐํฌ ํ
์คํธ๋ฅผ ํ๋ ๊ฒ์ด์์ผ๋ฏ๋ก ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
- ์ปจํ ์ด๋ ๋ด๋ถ์์ ๋น๋ ๊ณผ์ ์ด ๋๋๊ณ ํธ์คํธ PC์ ๋น๋ ํ์ผ์ ์ ์ก(๋ฐฐํฌ)๊น์ง๋ ํ ์ ์์ผ๋(docker cp ๋ช ๋ น์ด ์ฌ์ฉํด์), ์ปจํ ์ด๋ ๋ด๋ถ์์ ํธ์คํธ PC์๊ฒ ์์คํฌ๋ฆฝํธ๋ฅผ ์คํ์ํค๋ผ๊ณ ๋ช ๋ น์ ๋ด๋ฆด ๋ฐฉ๋ฒ์ด ๋์ ํ ์๊ฐ๋์ง ์์๋ค.
- ๋ฌผ๋ก ๋ฐฉ๋ฒ์ ์ฐพ์ผ๋ ค๊ณ ํ๋ฉด ํด๊ฒฐ์ฑ ์ด์ผ ์์๊ฒ ์ง๋ง ๋ณต์กํ ๊ฒ์ด ๋ปํ๊ณ ์ด๊ฑด ๋ง๊ทธ๋๋ก ์ค์ ์๋ฒ์ ์ ์ฉํด๋ณด๊ธฐ ์ ์ ๋ก์ปฌ ํ ์คํธ์๊ธฐ ๋๋ฌธ์ ๋์ปค ์ ํจ์ค ์ปจํ ์ด๋๋ฅผ ์ข ๋ฃํ๊ณ ๋ก์ปฌ PC์ ์ ํจ์ค๋ฅผ ์ค์นํ์ฌ ํ ์คํธํ๋ค.
๐ ๋ธ๋ฃจ/๊ทธ๋ฆฐ ๋ฐฐํฌ๋ฅผ ์ํ ์ค๋น
- ์ ๊ธ์ ๊ทธ๋๋ก ๋ฐ๋ผํ๋ค๋ฉด ์คํ๋ง ๋ถํธ ์๋ฒ๋ฅผ ngrok์ผ๋ก ์ธ๋ถ์ ๋ ธ์ถ์ํค๊ณ ์ด๋ฅผ ๊นํ๋ธ์ ์นํ ์ ์ด์ฉํด ์ ํจ์ค ์ํฌ์คํ์ด์ค์ ํด๋ก ํ๋ ๊ฒ๊น์ง ๋์ด์์ ๊ฒ์ด๋ค.
- ์ด ๊ธ์ ์ดํ์ ๊ณผ์ ๋ถํฐ ์ค๋ช
ํ๋ค.
- ์ด ๊ธ์ ๋ง์ง๋ง ํ ์คํธ์์๋ ngrok์ผ๋ก ์ธ๋ถ์ ์๋ฒ๋ฅผ ๋ ธ์ถ ์์ผ ๋ก์ปฌ์์ ๊นํ๋ธ ๋ ํ์งํ ๋ฆฌ๋ก ํธ์ํ๋ ๊ฑธ ํธ๋ฆฌ๊ฑฐ๋ก ๋ฐฐํฌ ์๋ํํ๋ ํ ์คํธ ๊ณผ์ ์ ์๋ตํ๊ณ ์ ํจ์ค UI์์ ์ง์ ๋น๋ํ๊ธฐ ๋ฒํผ์ ๋๋ฌ ์งํํ๋ค.(๋ฌด์ค๋จ ๋ฐฐํฌ๋ง ํ ์คํธ ์งํ)
- ๋ฐ๋ผ์ ngrok๊น์ง ํด๋ณด๊ณ ์ถ๋ค๋ฉด(๋ฐฐํฌ ์๋ํ) ์ ๊ธ์ ์ฐธ๊ณ ํ์ฌ ํ ์คํธํ๋ฉด ๋๋ค.
- ๋ด๊ฐ ๋ง๋ค ๋ธ๋ฃจ/๊ทธ๋ฆฐ ๋ฌด์ค๋จ ๋ฐฐํฌ ๊ณผ์ ์ ๋ํ ๊ณํ์


- ์์ ๊ฐ์ ๋ฐฉ์์ด๋ค.
- ์ค์ 3ํธ ๊ธ์ ๋ฐฐํฌํ ์คํธ์์๋ ๊นํ๋ธ ํธ์ ๊ณผ์ ์ ์๋ตํ๊ณ ์ ํจ์ค์์ ์ง์ ๋น๋ํ๋ ๋ฐฉ์์ผ๋ก ์งํํ๋ค.
https://suzuworld.tistory.com/416
์ ํจ์ค(jenkins)์ ๋ํด ์์๋ณด๊ณ ๋ฌด์ค๋จ ๋ฐฐํฌ ๊ณํ์ ์ธ์๋ณด์
๐ก ์ฌ๋ด ํ๋ก์ ํธ์ ์ ํจ์ค๋ฅผ ์ ์ฉํ์ฌ ๊ธฐ์กด์ ๊ณ ์ ์ ์ธ ๋น๋ & ๋ฐฐํฌ ๋ฐฉ์์์ ๋ฒ์ด๋๋ ๊ณผ์ ์ ๊ธฐ๋กํ๋ ค๊ณ ํ๋ค. ๐ค What is Jenkins? ์ ํจ์ค(Jenkins)๋ ์ง์์ ์ธ ํตํฉ(Continuous Integration)๊ณผ ์ง์์ ์ธ
suzuworld.tistory.com
- ์์ธํ ๋ฐฐํฌ ์ค๋ช ์ ์ด ๊ธ์์ ํ์ธํ ์ ์๋ค.
- ์ฝ๊ณ ์๋์ ๋ด์ฉ์ ๋ด์ผ ์งํ์ํฉ์ด ์ฝ๊ฒ ์ดํด๋ ๊ฒ์ด๋ค.
- ์ ๊ธ์์๋ ๋ก์ปฌ ์๋ฒ์์ ์ธ๋ถ ์๋ฒ๋ก ๋ฐฐํฌํ๋ ๋ฐฉ์์ ์ค๋ช ํ๋๋ฐ(๋ก์ปฌ -> ๊นํ๋ธ -> ์ธ๋ถ ์๋ฒ ์ ํจ์ค -> ์ธ๋ถ ์๋ฒ ๋ฐฐํฌ)
- ์ฌ๊ธฐ์ ์งํํ ํ
์คํธ์์๋ (๋ก์ปฌ -> ๊นํ๋ธ -> ๋ก์ปฌ ์ ํจ์ค -> ๋ก์ปฌ ๋ฐฐํฌ)๋ก ์งํ ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝ๋์๋ค๋ ์ ์ ์ฐธ๊ณ ํ๊ธธ ๋ฐ๋๋ค.
- ํฌ๊ฒ ๋ฌ๋ผ์ง์ง๋ ์์๊ณ ๊ทธ์ ์ธ๋ถ์๋ฒ๋ก ๋ฐฐํฌํ๋๋ ๋ก์ปฌ์ ๋ฐฐํฌํ๋๋์ ์ฐจ์ด๊ฐ ์์ ๋ฟ์ด๋ค.
- ๋ก์ปฌ -> ๊นํ๋ธ๋ ํ ์คํธ ๊ณผ์ ์์ ์๋ตํ๋ค.
โ๏ธ ์คํ๋ง๋ถํธ ์๋ฒ ์ธํ
import lombok.RequiredArgsConstructor;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;
@RestController
@RequiredArgsConstructor
public class MainController {
private final Environment environment;
@GetMapping("/")
public String getVersion() {
return "์ด ์๋ฒ๋ V1์
๋๋ค. ๋น๋ ํ
์คํธ์
๋๋ท!!!";
}
@GetMapping("/profile")
public String getProfile() {
return Arrays.stream(environment.getActiveProfiles()).findFirst().orElse("default");
}
}
- ๋จผ์ ์คํ๋ง๋ถํธ ์๋ฒ๋ฅผ ์ธํ ํ๊ฒ ๋ค.
- ์คํ๋ง ๋ถํธ ํ๋ก์ ํธ๋ฅผ ๋ง๋ ๋ค ์ปจํธ๋กค๋ฌ ํด๋์ค์ ์ ๋ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ค.
- getVersion()์ ๊ฒฝ์ฐ localhost:8080์ผ๋ก ์ ์ํ๋ฉด ์ ๋ฆฌํด๋ฌธ์ด ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
- getProfile()์ ๊ฒฝ์ฐ์๋ localhost:8080/profile๋ก ์ ์ํ๋ฉด ์คํ๋ง๋ถํธ ์๋ฒ์ ํ๋กํผํฐ ํ๋กํ์ด ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.



- ๋ก์ปฌ ์๋ฒ์๋ ์ด 3๊ฐ์ application.yml ํ์ผ์ด ์กด์ฌํ๋ค.
- application.yml์๋ spring.profiles.active: blue๋ง ์ ๋๋ค.
- ๋ก์ปฌ์์ ์ธํ ๋ฆฌ์ ์ด๋ก ์ง์ ์๋ฒ๋ฅผ ์คํํ ๋๋ default๋ก blue๋ฅผ ์คํํ ๊ฒ์ด๋ค.
- blue์ ํฌํธ๋ 8081์ด๋ฉฐ, ๊ทธ๋ฆฐ์ ํฌํธ๋ 8082์ด๋ค.
- ์ฌ๊ธฐ์ ์ฃผ์ํ ์ ์ ๋ฐ๋์" applicaiion-" ๋ค์ ์ํ๋ ํ๋กํ ์ด๋ฆ์ ์ ์ด์ผ ํ๋ค๋ ๊ฒ์ด๋ค.


- /profile๋ก ์๋ฒ์ ์ ์ํด ๋ณด์.
- application.yml์ blue๋ก ์ค์ ํ์ฌ ์คํํ๋ฉด blue๊ฐ ์ถ๋ ฅ๋๊ณ , green์ผ๋ก ์ค์ ํ๋ฉด green์ผ๋ก ์ถ๋ ฅ๋ ๊ฒ์ด๋ค.
๐ก build.gradle ์ค์

implementation 'org.springframework.boot:spring-boot-starter-actuator'
- ์ ์์กด์ฑ์ ์ถ๊ฐํ์.
- ๋์ค์ health check๋ฅผ ํ ๋ ์๋ฒ๊ฐ ์ ์์ ์ผ๋ก ์คํ๋์๋์ง๋ฅผ ํ์ธํ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
- ์ปจํธ๋กค๋ฌ์ ๋ฐ๋ก get ์์ฒญ ๋ฉ์๋๋ฅผ ๋ง๋ค์ง ์์๋ ์ ์์กด์ฑ์ ์ถ๊ฐํ๋ ๊ฒ๋ง์ผ๋ก ์๋ฒ์ ์ ์ ์คํ ์ฌ๋ถ๋ฅผ ์ฒดํฌํ ์ ์๋ api๊ฐ ์๋์ผ๋ก ์ถ๊ฐ๋๋ค.
- api ์ํธํฌ์ธํธ๋ /actuator/health์ด๋ค.
- ์ค์ ๋ก ์ ์ํด ๋ณด๋ฉด json ํํ๋ก "UP"์ด๋ผ๊ณ value๊ฐ ์ถ๋ ฅ๋จ์ ํ์ธํ ์ ์๋ค.
- ์ด "UP"์ด๋ผ๋ ๋ฌธ์๋ ์ ์คํฌ๋ฆฝํธ์์ ์๋ฒ์ ์ ์ ์คํ ์ฌ๋ถ๋ฅผ ํ์ธํ ๋ ์ฌ์ฉ๋ ๊ฒ์ด๋ค.(health check)
๋ค์ ๊ธ์ ๊ณ์๋๋ค.
์ฐธ๊ณ
๋คผํผ
https://hyunminh.github.io/nonstop-deploy/