Java์ Spring Boot๋ฅผ ์ฃผ๋ ฅ์ผ๋ก ๊ฐ๋ฐํ๋ ๋ง์ ๋ฐฑ์๋ ๊ฐ๋ฐ์์๊ฒ ๋ฐฐํฌ๋ ํญ์ ์ค์ํ ๊ณผ์ ๋ค. JAR ํ์ผ์ ๋ง๋ค๊ณ ๋ฆฌ๋
์ค ์๋ฒ์ ์ฌ๋ฆฐ ๋ค ์ ์คํฌ๋ฆฝํธ๋ฅผ ์ง์ ์คํํ๊ณ Systemd ์๋น์ค๋ก ๋ฑ๋กํ๋ ๊ณผ์ ์ ์๊ฐ๋ณด๋ค ์์ด ๋ง์ด ๊ฐ๋ ์ผ์ด๋ค.
์ด๋ฒ์ Baeldung์์ ์๊ฐ๋ ‘jdeb๋ฅผ ํ์ฉํ Java ๋น๋ ํ๋ก์ธ์ค ๊ฐ์ ’ ๊ธฐ์ฌ๋ฅผ ๋ณด๊ณ ์ด๋ฌํ ๋ฐฐํฌ ๊ณผ์ ์ ๋จ์ํ ํ ์ ์๋ ์ข์ ์๋ฃจ์
์ด ์์ด์ ๊ฐ๋จํ ์ ๋ฆฌํด ๋ดค๋ค.
jdeb ์ฃผ๋ชฉํด์ผ ํ ๊ธฐ๋ฅ 3๊ฐ์ง
jdeb๋ ๊ธฐ๋ณธ์ ์ผ๋ก java ํ๋ก์ ํธ์ JAR ํ์ผ์ Debian ํจํค์ง (ํํ Ubuntu๋ Debian ๊ณ์ด์์ ์ฌ์ฉํ๋ ์ค์น ํ์ผ)๋ก ๋ณํํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค.
ํฌ๋ก์ค ํ๋ซํผ ‘.deb’ ํจํค์ง ์์ฑ ์ง์
๊ธฐ์กด์๋ deb ํจํค์ง๋ฅผ ๋ง๋ค๋ ค๋ฉด ๋ณดํต Debian ๋๋ Ubuntu ๊ฐ์ ๋ฆฌ๋ ์ค ํ๊ฒฝ (ํน์ VM)์ด ํ์ํ๋ค. ํ์ง๋ง jdeb๋ ์์ java ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๋์ํ๋ฉฐ ๋ณ๋์ UNIX ์ ํธ๋ฆฌํฐ ์์ด๋ Windows๋ macOS ๊ฐ์ ํ๊ฒฝ์์ ์๋ฒฝํ๊ฒ deb ํ์ผ์ ์์ฑํ ์ ์๋ค. ์ด๋ ๊ฐ๋ฐ ํ๊ฒฝ์ ์ ์ฝ์ ํฌ๊ฒ ์ค์ฌ์ค๋ค.
Maven ๋ฐ Gradle, Ant ๋น๋ ์ฌ์ดํด์ ์๋ฒฝ ํตํฉ
jdeb๋ Maven Plugin๊ณผ Ant Task๋ฅผ ๋ชจ๋ ์ ๊ณตํ๋ค. Ant Task๋ฅผ ์ด์ฉํ์ฌ Gradle์์ ์ ์ฐํ๊ฒ ๊ตฌ์ฑํ ์๋ ์๋ค.
- Maven: pom.xml ๋ด์ <plugin> ์ค์ ์ผ๋ก ๊ฐ๋จํ๊ฒ ์ถ๊ฐ๋๋ฉฐ ๋ณดํต package ๋น๋ ํ์ด์ฆ์ ๋ฐ์ธ๋ฉํ์ฌ JAR ํ์ผ์ด ์์ฑ๋ ์งํ์ deb ํจํค์ง๊ฐ ์๋ ์์ฑ๋๋๋ก ์ค์ ํ ์ ์๋ค.
- Ant: <dev> ํ์คํฌ ์ ์๋ฅผ ํตํด ๋น๋ ํ์ผ์ ํตํฉ๋๋ค.
- Gradle: jdeb์ Ant Task ๊ธฐ๋ฅ์ ๊ฐ์ ธ์์ ์ ์ฐํ๊ฒ ๊ตฌ์ฑํ ์ ์๋ค.
์ง๊ด์ ์ธ ํ์ผ ๊ณ์ธต ๊ตฌ์กฐ ๋งคํ (dataSet๊ณผ mapper)
deb ํ์ผ ๋ด๋ถ์๋ ํจํค์ง ์ ๋ณด๊ฐ ๋ด๊ธด control.tar์ ์ค์ ์ค์น ํ์ผ์ด ๋ด๊ธด data.tar๊ฐ ์กด์ฌํ๋ค. jdeb๋ ์ด ์ค data.tar์ ๋ค์ด๊ฐ ํ์ผ์ ์ค์ ํ๋ ๊ฒ์ dataSet๊ณผ mapper๋ฅผ ํตํด์ ์ถ์ํํ๋ค.
์๋ฅผ ๋ค์ด ์ต์ข
JARํ์ผ์ /opt/myapp์ ๋ฃ๊ฑฐ๋ ์คํ ์คํฌ๋ฆฝํธ(Launcher)๋ฅผ /usr/bin์ ๋ฃ๋ ๋ฑ์ ๋ณต์กํ ๋ฆฌ๋
์ค ๊ฒฝ๋ก ์ค์ ์ Maven/Ant ์ค์ ํ์ผ ๋ด์์ ์ง๊ด์ ์ธ XML/Task ์ ์๋ก ์ฒ๋ฆฌํ ์ ์๋ค. ํนํ control ํ์ผ์ ๋ฉํ๋ฐ์ดํฐ(ํจํค์ง๋ช
, ๋ฒ์ , ์์กด์ฑ ๋ฑ) ์ ์๋ฅผ ์ง์ํ์ฌ ํจํค์ง ๊ตฌ์ฑ์ ์ค๋ฅ๋ฅผ ์ค์ฌ์ค๋ค.
jdeb ์ฌ์ฉ ๋ฐฉ๋ฒ
Maven๊ณผ Gradle์์ ์ด๋ป๊ฒ jdeb๋ฅผ ์ฌ์ฉํ์ฌ deb ํจํค์ง๋ฅผ ์์ฑํ๋์ง ํ์ธํด ๋ณด์.
- deb ํจํค์ง๋ช : deb-test-app
- FAT JAR ํ์ผ๋ช : spring-boot-jdeb.jar
- systemd service : my-app
jdeb-Maven
jdeb๋ Maven ๋น๋ ๋ผ์ดํ์ฌ์ดํด์ deb ํจํค์ง ์์ฑ์ ์ง์ ํตํฉํ๋ Maven ํ๋ฌ๊ทธ์ธ์ ์ ๊ณตํ๋ค. ํ๋ก์ ํธ์ pom.xml์์ ์ด๋ฅผ ๊ตฌ์ฑํ ์ ์๋ค. ์ผ๋ฐ์ ์ผ๋ก ํจํค์ง ๋จ๊ณ์ ๋ฐ์ธ๋ฉํ๊ณ jdeb goal์ ์คํํ๋ค. ํจํค์ง ๋ฉํ๋ฐ์ดํฐ์ data.tar ์์นด์ด๋ธ์ ํฌํจํ ํ์ผ ์ธํธ๋ฅผ ์ ์ํด์ผ ํ๋ค. ํ๋ก์ ํธ๋ฅผ ํจํค์งํ๋ฉด deb ํ์ผ์ด ๋ค๋ฅธ ์ํฐํฉํธ์ ํจ๊ป ์์ฑ๋๋ค.
deb ํจํค์ง ๊ตฌ์ฑ์ ํ์ํ ํ์ผ ์์น

deb ํจํค์ง ์ค์น ๋ฐ ์ญ์ ์ ์คํ๋ ์คํฌ๋ฆฝํธ ์์น๋ src/main/resources/deb/control ์ด๋ค.
deb ํจํค์ง ์ค์น์ systemd์ ๋ฑ๋กํ๊ธฐ ์ํ service ํ์ผ์์น๋ src/main/resources/deb/systemd ์ด๋ค.
ํ์ผ ์์น๋ ๊ผญ resources์ ์์ ํ์๋ ์๋ค. src/deb ๋ฐ์ ๊ตฌ์ฑํด๋ ๋๊ณ .. ๊ฒฝ๋ก ์ค์ ๋ง ์ ๋ง์ถ๋ฉด ๋๋ค.
control ํ์ผ ์์ฑ
๋จผ์ ํจํค์ง์ ๋ฉํ๋ฐ์ดํฐ ํ์ผ์ ๋ง๋ค์ด์ผ ํ๋ค.
ํ์ผ ๊ฒฝ๋ก๋ src/main/resources/deb/control/control ์ด๋ผ๊ณ ํด๋ณด์.
Package: deb-test-app
Version: 1.0.0
Section: misc
Priority: optional
Architecture: all
Maintainer: My Name <my.email@example.com>
Description: This is my Spring Boot Application package
distribution via jdeb.Plaintextcontrol์ ํ์ํ ํ๋ ์ ๋ณด๋ https://www.debian.org/doc/debian-policy/ch-controlfields.html๋ฅผ ์ฐธ์กฐ.
์ ์์์ ํจํค์ง ๋ช
์ dep-test-app ์ด๋ค.
postinst ์คํฌ๋ฆฝํธ ํ์ผ
deb ํจํค์ง ํ์ผ์ด ์ค์น๋ ์ดํ์ ์คํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ์ ์ํ๋ค. ์ด๋ฆ์ postinst ๋ก ๋ง์ถฐ์ผ ํ๋ค.
#!/bin/sh
# ํจํค์ง ํ์ผ์ด /opt/myapp์ ์ค์น๋ ์งํ ์คํ๋๋ ์คํฌ๋ฆฝํธ
# ์๋ฌ ๋ฐ์ ์ ์ค๋จ
set -e
# ์ค์น(configure) ๋จ๊ณ์ผ ๋๋ง ์คํ
if [ "$1" = "configure" ]; then
echo "Systemd ์๋น์ค ๋ฑ๋ก ๋ฐ ์ฌ์์ ์ค..."
# 1. systemd ์ค์ ์๋ก๊ณ ์นจ (์๋ก์ด .service ํ์ผ ์ธ์)
if command -v systemctl >/dev/null; then
sudo systemctl daemon-reload
# 2. ๋ถํ
์ ์๋ ์คํ ๋ฑ๋ก
sudo systemctl enable my-app
# 3. ์๋น์ค (์ฌ)์์
sudo systemctl restart my-app
fi
# 4. ๊ถํ ๋ณด์ (ํ์ํ ๊ฒฝ์ฐ)
chown -R root:root /opt/myapp
fi
exit 0Bash์ ์์์ systemd ์๋น์ค๋ช ์ my-app ์ด๋ค.
prerm ์คํฌ๋ฆฝํธ ํ์ผ
deb ํจํค์ง๊ฐ ์ ๊ฑฐ ๋๊ฑฐ๋ ์ ๊ทธ๋ ์ด๋ ๋๋ ๊ฒฝ์ฐ ์คํ๋๋ ์คํฌ๋ฆฝํธ๋ค.
#!/bin/sh
# ํจํค์ง๋ฅผ ์ญ์ (remove) ํ๊ฑฐ๋ ์
๊ทธ๋ ์ด๋ ์ง์ ์ ์คํ๋จ
set -e
# ์ญ์ (remove) ๋๋ ์
๊ทธ๋ ์ด๋(upgrade) ์ ์คํ
if [ "$1" = "remove" ] || [ "$1" = "upgrade" ]; then
echo "์๋น์ค ์ค์ง ์ค..."
if command -v systemctl >/dev/null; then
sudo systemctl stop my-app
fi
fi
exit 0Bashsystemd service ๋ฑ๋ก ํ์ผ
[Unit]
Description=My Spring Boot Application
After=syslog.target
[Service]
User=root
# ์ค์ ์ค์น๋ ๊ฒฝ๋ก๋ฅผ ์ ์ด์ผ ํฉ๋๋ค!
ExecStart=/usr/bin/java -jar /opt/myapp/spring-boot-jdeb.jar
SuccessExitStatus=143
[Install]
WantedBy=multi-user.targetBash์ ์์์ fat jar ํ์ผ๋ช ์ spring-boot-jdeb.jar ์ด๋ค.
pom.xml plugin ์ค์
<plugin>
<groupId>org.vafer</groupId>
<artifactId>jdeb</artifactId>
<version>1.14</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>jdeb</goal></goals>
<configuration>
<!-- control ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ง์ ํ๋ค. ๋๋ ํ ๋ฆฌ๊น์ง ์ง์ ํ๋ ๊ฒ์ ์ ์!! -->
<controlDir>${project.basedir}/src/main/resources/deb/control</controlDir>
<!-- ๋ฐฐํฌํ ํ์ผ๋ค์ dataSet์ ์ ์ํ๋ค. -->
<dataSet>
<data>
<!-- systemd service ๋ฑ๋ก ํ์ผ ์์น๋ฅผ ์ค์ ํ๋ค. -->
<src>${project.basedir}/src/main/resources/deb/systemd/my-app.service</src>
<type>file</type>
<mapper>
<type>perm</type>
<prefix>/lib/systemd/system</prefix>
</mapper>
</data>
<data>
<src>${project.build.directory}/${project.build.finalName}.jar</src>
<type>file</type>
<mapper>
<type>perm</type>
<prefix>/opt/myapp</prefix>
</mapper>
</data>
</dataSet>
</configuration>
</execution>
</executions>
</plugin>XMLpackaing ํ๊ธฐ
$> ./mvnw clean packageBashpackage๋ฅผ ์ํํ๋ฉด target ๋๋ ํ ๋ฆฌ์ ๋ค์๊ณผ ๊ฐ์ ํจํค์ง ํ์ผ์ด ์์ฑ๋๋ค.
- spring-boot-jdeb_0.0.1~SNAPSHOT_all.deb
- spring-boot-jdeb.jar
spring-boot-jdeb_0.0.1~SNAPSHOT_all.deb ํ์ผ์ด ๋ฐ๋ก deb ํจํค์ง ํ์ผ์ด๋ค. ํด๋น ํจํค์ง ํ์ผ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ๋ค.
ubuntu@ubuntu-jammy:~$ dpkg -c spring-boot-jdeb_0.0.1~SNAPSHOT_all.deb
drwxr-xr-x root/root 0 2025-12-08 22:13 ./lib/
drwxr-xr-x root/root 0 2025-12-08 22:13 ./lib/systemd/
drwxr-xr-x root/root 0 2025-12-08 22:13 ./lib/systemd/system/
-rw-r--r-- root/root 257 2025-12-08 22:13 ./lib/systemd/system/my-app.service
drwxr-xr-x root/root 0 2025-12-08 22:13 ./opt/
drwxr-xr-x root/root 0 2025-12-08 22:13 ./opt/myapp/
-rw-r--r-- root/root 20840680 2025-12-08 22:13 ./opt/myapp/spring-boot-jdeb.jarBashdeb ํ์ผ์ ์ค์นํ๋ฉด my-app.service๋ /lib/systemd/system์ ์ค์น๋๊ณ spring-boot-jdeb.jar๋ /opt/myapp์ ์ค์น๋๋ค.
์ค์นํด๋ณด๊ธฐ
๋จผ์ ํจํค์ง ์ ๋ณด๋ฅผ ํ์ธํด ๋ณด์.
ubuntu@ubuntu-jammy:~$ dpkg --info spring-boot-jdeb_0.0.1~SNAPSHOT_all.deb
new Debian package, version 2.0.
size 21000796 bytes: control archive=1006 bytes.
233 bytes, 9 lines control
133 bytes, 2 lines md5sums
664 bytes, 25 lines * postinst #!/bin/sh
341 bytes, 14 lines * prerm #!/bin/sh
Package: deb-test-app
Version: 1.0.0
Section: misc
Priority: optional
Architecture: all
Installed-Size: 22716
Maintainer: My Name <my.email@example.com>
Description: This is my Spring Boot Application package
distribution via jdeb.Bash์์์ ์ ์ํ control, postinst, prerm ํ์ผ์ด ํฌํจ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
dataSet์ ์ ์ํ ํ์ผ์ ๋ฐฐํฌ ๋์ ํ์ผ์ด๋ฏ๋ก ๋ฉํ ์ ๋ณด(–info)์๋ ํฌํจ๋์ง ์๋๋ค.
์ด์ ํจํค์ง๋ฅผ ์ค์น ํด๋ณด์.
ubuntu@ubuntu-jammy:~$ sudo dpkg -i spring-boot-jdeb_0.0.1~SNAPSHOT_all.deb
Selecting previously unselected package deb-test-app.
(Reading database ... 66578 files and directories currently installed.)
Preparing to unpack spring-boot-jdeb_0.0.1~SNAPSHOT_all.deb ...
Unpacking deb-test-app (1.0.0) ...
Setting up deb-test-app (1.0.0) ...
Systemd ์๋น์ค ๋ฑ๋ก ๋ฐ ์ฌ์์ ์ค...
Created symlink /etc/systemd/system/multi-user.target.wants/my-app.service โ /lib/systemd/system/my-app.service.Bash๋ง์ง๋ง ‘์๋น์ค ๋ฑ๋ก ๋ฐ ์ฌ์์ ์ค…’ ๋ฉ์์ง๊ฐ ์ถ๋ ฅ๋๋ ๊ฑธ๋ก ๋ด์ ์ฐ๋ฆฌ๊ฐ ์ ์ํ postinst ์คํฌ๋ฆฝํธ ์คํ์ด ๋๋ ๊ฒ์ ํ์ธ ํ ์ ์์ ๊ฒ์ด๋ค.
my-app ์ด๋ฆ์ผ๋ก systemd ์๋น์ค ๋ฑ๋ก์ด ์ ๋์๋์ง ํ์ธ ํด ๋ณด์.
ubuntu@ubuntu-jammy:~$ systemctl status my-app
โ my-app.service - My Spring Boot Application
Loaded: loaded (/lib/systemd/system/my-app.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2025-12-08 23:06:31 KST; 11s ago
Main PID: 2536 (java)
Tasks: 30 (limit: 1066)
Memory: 101.8M
CPU: 2.461s
CGroup: /system.slice/my-app.service
โโ2536 /usr/bin/java -jar /opt/myapp/spring-boot-jdeb.jarBashdep ํจํค์ง ์ด๋ฆ์ control ํ์ผ์ package ํ๋์ ์ ์ํ ๋ด์ฉ์ด๋ค. ์ฐ๋ฆฌ๋ ‘deb-test-app’ ์ผ๋ก ์ ์ ํ์ผ๋ฏ๋ก ์ค์น ์ฌ๋ถ๋ฅผ ํ์ธํด ๋ณด์.
ubuntu@ubuntu-jammy:/opt/myapp$ dpkg -l | grep deb-test-app
ii deb-test-app 1.0.0 all This is my Spring Boot Application packageBashcontrol ํ์ผ์ ์ ์ํ ๋ฉํ ์ ๋ณด๊ฐ ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
jdeb – Gradle
control, postinst, prerm, my-app.service ๋ maven ๊ณผ ๋์ผํ ๊ฒฝ๋ก์ ์๋ค๊ณ ๊ฐ์ ํ๋ค.
gradle์์ jdeb ์ ์๋ ๋ค์๊ณผ ๊ฐ๋ค.
plugins {
...
// bootJar ํ์คํฌ
id 'org.springframework.boot' version '3.5.7'
id 'io.spring.dependency-management' version '1.1.7'
...
}
configurations{ jdeb }
dependencies { jdeb 'org.vafer:jdeb:1.14' }
task buildDeb {
group = 'distributions'
description = 'Creates a Debian package using jdeb'
dependsOn 'bootJar'
doLast {
// 1. jdeb ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ก๋
ant.taskdef(name: 'deb', classname: 'org.vafer.jdeb.ant.DebAntTask', classpath: configurations.jdeb.asPath)
// 2. bootJar๋ก ์์ฑ๋ ํ์ผ ๊ฐ์ ธ์ค๊ธฐ
def jarFile = tasks.bootJar.archiveFile.get().asFile
// 3. deb ํจํค์ง ์์ฑ ์์
ant.deb(destfile: "${buildDir}/distributions/spring-boot-jdeb.deb", control: "src/main/resources/deb/control") {
// jar ํ์ผ ๋ฐฐ๋ก ์ค์
data(src: jarFile, type: "file") {
mapper(type: "perm", prefix: "/opt/myapp")
}
// systemd ์๋น์ค ํ์ผ ๋ฐฐํฌ ์ค์
data(src: file("src/main/resources/deb/systemd/my-app.service"), type: "file") {
mapper(type: "perm", prefix: "/lib/systemd/system", user: "root", group: "root", filemode: "644")
}
}
}
}Groovydistributions > buildDeb ํ์คํฌ๊ฐ ์์ฑ๋๋ค. gradle์ ๊ฒฝ์ฐ์๋ maven๊ณผ ๋ฌ๋ฆฌ bootJar ํ์คํฌ๋ฅผ ํตํด ์์ฑ๋ fat jar๊ฐ ํ์ํ๋ค.(dependsOn ‘bootJar’)
IntelliJ๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์ฐ์ธก Gradle ๋ฉ๋ด > Tasks > distributions > buildDeb ๋ฅผ ์คํ ํ๋ค.
CLI ๋ช
๋ น์ ์๋ ๋ช
๋ น์ ์คํํ๋ค.
$> ./gradlew clean buildDebBash๊ฒฐ๊ณผ๋ build/distributions์ deb ํ์ผ์ด ์์ฑ๋๋ค.
Java ๊ฐ๋ฐ์ด ์ฃผ๋ก ์ปจํ
์ด๋(Docker) ํ๊ฒฝ์์ ์ด๋ฃจ์ด์ง๋ ์ถ์ธ์ง๋ง, ์จํ๋ ๋ฏธ์ค ํ๊ฒฝ์ ์ง์ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ฐฐํฌ ํด์ผ ํ๋ ์ํฉ์ ์ฌ์ ํ ๋ง์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ค. ์ด ๋ jdeb๋ JAR ํ์ผ์ ๋ฆฌ๋
์ค ํจํค์ง ๋ฐฐํฌ์ ํ์ค์ธ deb ํํ๋ก ์๋ ๋ณํํ์ฌ ์๋ ๋ฐฐํฌ ๋ฐ ์คํฌ๋ฆฝํธ ๊ด๋ฆฌ์ ๋ถ๋ด์ ์ค์ฌ ์ค ๊ฒ์ด๋ผ๊ณ ๊ธฐ๋ํ๋ค.
๋ฐฐํฌ์ ์์ ์ฑ๊ณผ ์์ฐ์ฑ์ ๋์์ ์ก๊ณ ์ถ๋ค๋ฉด ‘jdeb’ ํ๋ฌ๊ทธ์ธ์ Maven, Ant, Gradle ๋น๋ ํ๋ก์ธ์ค์ ๋์
ํด ๋ณด๋ ๊ฒ์ ๊ฐ๋ ฅ๋ํ๊ฒ ์ถ์ฒํ๋ค.
์ฐธ๊ณ ์ฌ์ดํธ
https://www.baeldung.com/java-debian-deb-packages-jdeb
