๐Ÿ“— [Spring Boot] .jar ๋ฐฐํฌ ํ›„ resources ํŒŒ์ผ ๊ฒฝ๋กœ ์ฐพ๊ธฐ

hmyanghmยท2021๋…„ 8์›” 23์ผ
2

SPRING BOOT

๋ชฉ๋ก ๋ณด๊ธฐ
1/2
post-thumbnail

ํ˜„์žฌ ์ง„ํ–‰ํ•˜๊ณ  ์žˆ๋Š” ํ”„๋กœ์ ํŠธ ๊ฐœ๋ฐœ์„œ๋ฒ„๋ฅผ ๋„์ปค์— jar ํŒŒ์ผ๋กœ ์ด๋ฏธ์ง€ํ™” ์‹œ์ผœ์„œ ๋„์šฐ๊ณ  ์žˆ๋‹ค.
๋ฌธ์ œ ์—†์ด ์ง„ํ–‰๋˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ, ๊ฐ€๋ณ๊ฒŒ ์ƒ๊ฐํ–ˆ๋˜ resource ํŒŒ์ผ ์•ˆ์— ์žˆ๋Š” .dat ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ์ฝ์–ด์˜ค๋Š” ๊ณผ์ •์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.


๐Ÿ“Œ ๋ฌธ์ œ ๋ฐœ์ƒ ๋‚ด์šฉ

local์—์„œ๋Š” ๋ฌธ์ œ์—†์ด ํ•ด๋‹น ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ์ž˜ ์ฝ์–ด์˜ค๋Š”๋ฐ, ๋ฐฐํฌํ•œ .jar ํŒŒ์ผ์—์„œ๋Š” ํ•ด๋‹น ํŒŒ์ผ์ด ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” FileNotFoundException ์—๋Ÿฌ๊ฐ€ ๊ณ„์† ๋‚˜ํƒ€๋‚ฌ๋‹ค.๐Ÿ‘ฟ๐Ÿ‘ฟ๐Ÿ‘ฟ

์ฒ˜์Œ์—” .properties์— ๊ฒฝ๋กœ๋ฅผ ์„ค์ •ํ•ด๋‘์—ˆ๋Š”๋ฐ ์ด๊ฒŒ ์ž˜๋ชป๋œ๊ฑด๊ฐ€ ์‹ถ์–ด์„œ ์ˆ˜์ •ํ•ด๋ณด์•˜๋‹ค.
ํ•˜์ง€๋งŒ ์‹คํŒจํ–ˆ๊ณ  ๊ตฌ๊ธ€๋ง ํ–ˆ์„ ๋•Œ getClass().getURL() ๋˜๋Š” getClass().getClassLoader().getURL() ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์œผ๋กœ ํ•ด๊ฒฐํ•œ ์‚ฌ๋žŒ๋“ค๋„ ์žˆ์–ด์„œ ๋‚˜๋„ ์ ์šฉํ•ด๋ณด์•˜์ง€๋งŒ ์ด ๋ฐฉ๋ฒ• ์—ญ์‹œ ์‹คํŒจ๐Ÿ˜ฅ

์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์ƒ๊ฐํ•ด๋ณด์ž๋Š” ์ƒ๊ฐ์œผ๋กœ ๋ฐฐํฌํ•œ .jar ํŒŒ์ผ์— ๋Œ€ํ•œ ๋ฃจํŠธ ๊ฒฝ๋กœ log๋ฅผ ํ™•์ธํ•ด๋ดค๋‹ค.
๐Ÿ‘‰ jar:file:/api.jar!/BOOT-INF/classes!/
๊ทธ๋ž˜์„œ BOOT-INF/classes๋ฅผ classpath๋ผ๊ณ  ์ƒ๊ฐํ•ด ์—ฌ๊ธธ ๊ธฐ์ค€์œผ๋กœ ์žก๊ณ  ๊ฒฝ๋กœ๋ฅผ ์ฐพ์œผ๋ ค ํ–ˆ์ง€๋งŒ ๋˜ ์‹คํŒจ!
๊ตฌ๊ธ€๋ง ํ•ด๋ณด๋‹ˆ ์†Œ์Šค์ฝ”๋“œ๊ฐ€ ์˜ฌ๋ผ๊ฐ€๊ธฐ ์ „ Spring์ด ์˜ฌ๋ผ๊ฐ€๊ณ  ์ด ๋•Œ Spring์ด ๋ฏธ๋ฆฌ resources์˜ ์œ„์น˜๋ฅผ ์žก์•„์ค˜์„œ ๊ทธ๋Ÿฐ๊ฒŒ ์•„๋‹๊นŒ ์‹ถ๋‹ค๐Ÿ˜ฉ

ClassPathResource๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๋ผ๋Š” ๋ง์— resource.getPath()๋กœ ํ•ด๋‹น ํŒŒ์ผ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์•„๋ณด๋ ค๊ณ  ํ–ˆ๋‹ค.

ClassPathResource resource = new ClassPathResource("folder/resourceFile.dat");
String path = resource.getPath();

ํ•˜์ง€๋งŒ classpath + folder/resourceFile.dat์œผ๋กœ ์•ž์„œ ์ง„ํ–‰ํ•œ ๊ฒƒ๊ณผ ๋™์ผํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ์ง„ํ–‰ํ•œ ๊ผด์ด ๋˜์–ด ๋˜ ๋‹ค์‹œ ์‹คํŒจํ•˜๊ณ  ๋ง์•˜๋‹ค.

๐Ÿ‘‰ local log ํ™”๋ฉด

๐Ÿ‘‰ ๋ฐฐํฌํ•œ .jar ํŒŒ์ผ log ํ™”๋ฉด (AWS CloudWatch)


๐Ÿ“Œ ๋ฌธ์ œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

์ •๋ง ๋งŽ์€ ์‹œ๋„ ๋์— ๋“œ๋””์–ด ๊ฒฝ๋กœ๋ฅผ ์ฐพ์•˜๋‹ค!! ๋งŒ์„ธ๐Ÿ™Œ

InputStream inputStream = new ClassPathResource("folder/resourceFile.dat").getInputStream();
File file =File.createTempFile("resourceFile",".dat");
try {
    FileUtils.copyInputStreamToFile(inputStream, file);
} finally {
    IOUtils.closeQuietly(inputStream);
}

jarํŒŒ์ผ์€ class file, resource์™€ nested jar๋“ค๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋Š”๋ฐ ์—ฌ๊ธฐ์„œ resource์˜ URL์€ ์ƒ๋‹จ .jar ๋ฃจํŠธ ๊ฒฝ๋กœ๋ฅผ ์ฐธ๊ณ ํ•ด๋ณด๋ฉด jar://๋กœ ์‹œ์ž‘ํ•˜๋Š” ์ฃผ์†Œ๋ฅผ ๊ฐ€์ง€๊ฒŒ ๋œ๋‹ค.
๋กœ์ปฌ๋กœ ์‹คํ–‰ํ–ˆ์„ ๋• ์‹ค์ œ resource ํŒŒ์ผ์ธ file:// ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— File ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ์ค„ ์ˆ˜ ์žˆ์–ด ํ•ด๋‹น ๊ฒฝ๋กœ๋ฅผ ์ฐพ์•„์˜ฌ ์ˆ˜ ์žˆ์—ˆ๊ณ , .jar ํŒŒ์ผ์€ ํ•ด๋‹น ๊ฒฝ๋กœ๋ฅผ ์ฐพ์•„์˜ฌ ์ˆ˜ ์—†์—ˆ๋˜ ๊ฒƒ์ด์—ˆ๋‹ค!

๋”ฐ๋ผ์„œ, classloader์—๊ฒŒ ์ฒ˜๋ฆฌ๋ฅผ ์œ„์ž„ํ•œ ํ›„ InputStream์„ ํ†ตํ•ด ์ฒ˜๋ฆฌํ–ˆ๋‹ค.

// ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์ง€์ •๋œ tmp ๋””๋ ‰ํ† ๋ฆฌ์— ์ž๋™์œผ๋กœ ์ž„์‹œ ํŒŒ์ผ์„ ์ƒ์„ฑ์‹œํ‚จ๋‹ค.
File.createTempFile(prefix, suffix)

// InputStream์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด ์ž„์‹œ ํŒŒ์ผ๋กœ ์จ์ค€๋‹ค.
FileUtils.copyInputStreamToFile(inputStream, tempFile)

์ •๋ง ์—ฌ๋Ÿฌ๋ฒˆ์˜ ๊ตฌ๊ธ€๋ง๊ณผ ๋งŽ์€ ์‹œ๋„ ๋์— ํ•ด๊ฒฐํ•œ ๊ฒฝ๋กœ ์ฐพ๊ธฐ์˜€๋‹ค.๐Ÿ‘
์—ญ์‹œ ๊ฐœ๋ฐœ์€ ์–ด๋ ต๊ณ  ๊ณต๋ถ€ํ•  ๊ฒƒ์ด ๋งŽ์ง€๋งŒ, ํ•ด๊ฒฐํ•˜๊ณ  ๋‚˜๋ฉด ๋„ˆ๋ฌด ํ–‰๋ณตํ•˜๋‹ค. ์•ผํ˜ธ๐Ÿ˜Š๐Ÿ˜Š๐Ÿ˜Š

profile
Back-end developer

0๊ฐœ์˜ ๋Œ“๊ธ€