URL์ด ์ด์ํด์! Java์ Spring ์ค ๋ฒ์ธ์ ๋๊ตฌ?
URL์ด ์ด์ํด์! Java์ Spring ์ค ๋ฒ์ธ์ ๋๊ตฌ? ๊ด๋ จ
์์ฝ
์ด ๊ธ์ ์นด์นด์คํ์ด ์๋ฆผํผ๋ ์๋น์ค์์ ๋ฐ์ํ ์ฅ์ ์์ธ๊ณผ ํด๊ฒฐ ๊ณผ์ ์ ๋ค๋ฃน๋๋ค. ์๋ฆผํผ๋์ ๋๋ฉ URL์ ๊ฐ๊ณตํ๋ ์ค ๋ฐ์ํ ๋ฌธ์ ๋ฅผ ๋ถ์ํ๋ฉฐ, Java์ URI ํด๋์ค์ Spring์ UriComponentsBuilder
ํด๋์ค ๊ฐ์ ๋ถ์ผ์น๊ฐ ์ฅ์ ์ ์์ธ์ด์์์ ์ค๋ช
ํฉ๋๋ค. ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด fromUriString
๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ์ ์ํ๋ฉฐ, ๊ฒฝํ์ ๊ณต์ ํ๋ ๊ธ์
๋๋ค.
๐ก **๋ฆฌ๋ทฐ์ด ํ์คํ**
hyeoni.c ํ์ ์ ์ฌ์ฉํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ ์ฑ ๊ณผ ๋ด๋ถ ๊ตฌํ์ ์ดํด๋ณด๋ฉฐ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด ๊ฐ๋ ๊ณผ์ ์ ์ฌ๋ฐ๊ฒ ํ์ด๋ด์์ต๋๋ค. ์ ์ฌํ ๊ฒฝํ์ ๊ฐ์ง์ , ์์ผ๋ก ๋ง์ฃผํ ์ ์๋ ๋ชจ๋ ๋ถ๋ค์๊ฒ ์ถ์ฒํฉ๋๋ค!
daisy.dani URI ์ ๋ณด๊ฐ ์ ๊ฐ์๊ธฐ ์ฌ๋ผ์ก์๊น์? ์ด ๊ธ์์ ์์ธ์ ํํค์น๊ณ , ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์๋์ง ์์๋ด ์๋ค!
์์ํ๋ฉฐ
Spring ํ๋ ์์ํฌ๊ฐ ์ ๊ณตํ๋ UriComponentsBuilder
ํด๋์ค๋ฅผ ์์๋์? UriComponentsBuilder
ํด๋์ค๋ URL์ ์ฝ๊ฒ ๋ค๋ฃจ๊ธฐ ์ํ ์ ํธ ํด๋์ค์
๋๋ค. ์ด๋ฒ์ URL์ ์์ ํ๊ธฐ ์ํด UriComponentsBuilder
ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ ์ค ์๋น์ค ์ฅ์ ๊ฐ ๋ฐ์ํ๋๋ฐ์. ์์ธ์ ๋ถ์ํด ๋ณด๋ java.net.URI
ํด๋์ค์ UriComponentsBuilder
ํด๋์ค ์ฌ์ด์์ ๊ฝค๋ ํฅ๋ฏธ๋ก์ด ์ผ์ด ์ด๋ค์ง๊ณ ์์ต๋๋ค. ๋ฌด์จ ์ผ์ธ์ง ๊ถ๊ธํ์ง ์์ผ์ ๊ฐ์? ์ง๊ธ๋ถํฐ ํจ๊ป ๋น์์ ์ํฉ ์์ผ๋ก ๋ค์ด๊ฐ ๋ณด๊ฒ ์ต๋๋ค.
์๋ ํ์ธ์. ์ฑ๋์๋ฒ์ ๋์ ๋ ์ธ์ ๋๋ค. ์ฑ๋์๋ฒ์ ๋์ ์ฌ๋ฌ๋ถ์ด ์นด์นด์คํ์ด์ ๋ค์ํ ์๋น์ค์ ํํ์ ๋ง์ฃผํ๊ณ ํ์ํ ์ ์๋๋ก ํ ํญ, ํํ ํญ, ๊ฒฐ์ ํญ ๋ฑ ๋ค์ํ ์ ๋ฉด ์๋น์ค๋ฅผ ๊ฐ๋ฐํ๊ณ ์์ต๋๋ค. ์ด๋ฌํ ์๋น์ค์๋ ์ด ๊ธ์ ๋ฐฐ๊ฒฝ์ด ๋๋ ์๋ฆผํผ๋๋ ์กด์ฌํ๋๋ฐ์. ์นด์นด์คํ์ด ์ฑ์ ์ฌ์ฉํ์ ๋ค๋ฉด ์๋ ์ฌ์ง ์ ๊ณต๊ฐ, ์๋ฆผํผ๋๊ฐ ์ต์ํ์ค ๊ฒ๋๋ค.
์๋ฆผํผ๋๋ ์ฌ๋ฌ๋ถ์ด ์ธ์ ๋ ํธํ๊ฒ ์๋ฆผ์ ํ์ํ๊ณ ์ํ๋ ์๋น์ค๋ฅผ ๋ฐฉ๋ฌธํ ์ ์๋๋ก ๋ ธ๋ ฅํ๊ณ ์์ต๋๋ค. ํด๋ฆญํ๋ฉด ๋ฉ์์ง๊ฐ ์ฌ๋ผ์ง๋ OS ์๋ฆผ ์ผํฐ์ ๋ฌ๋ฆฌ ๋ฉ์์ง๋ฅผ ๋ค์ ๋ณผ ์ ์๋๋ก 30์ผ ๋์ ๋ณด๊ดํ๊ณ ์๊ณ ์. ์๋ฆผ์ ์๋ณํ๊ธฐ ํธํ๋๋ก ๋ฉ์์ง์ ์๋น์ค๋ฅผ ํ์ํ๊ฑฐ๋, ์ํ๋ ์ข ๋ฅ์ ์๋ฆผ์ ํ์ํ๊ธฐ ํธํ๋๋ก ํํฐ ๋ฑ์ ๊ธฐ๋ฅ์ ์ ๊ณตํ๊ณ ์์ต๋๋ค.
๊ธฐ: ๋ฌด์จ ์ผ์ด ๋ฐ์ํ๋๊ฐ
์๋ฆผํผ๋๋ฅผ ๊ตฌ์ฑํ๋ ๋ฐ์ดํฐ๋ ์ฑํธ์๋ก ๋ฐ์กํ๋ ๋ฉ์์ง์ ๊ธฐ๋ฐํ๊ณ ์์ต๋๋ค. ๊ทธ๋์ ์๋ฆผํผ๋๋ OS ์๋ฆผ ์ผํฐ ํ๊ฒฝ์ ๋ง์ถฐ์ง ๋ฐ์ดํฐ๋ค์ ๋ชฉ์ ์ ๋ง๊ฒ ๊ฐ๊ณตํด์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ์ด ๊ณผ์ ์์ ์๋ฆผํผ๋๋ ๋ฐ๋ณต๋๋ ํค์๋๋ฅผ ์ ๊ฑฐํ๋ ๋ฑ ๋ฌธ๊ตฌ๋ฅผ ๊ฐ๊ณตํ๊ณ ์๋๋ฐ์. ์ด๋ ๋ ๋ฉ์์ง์ ๋๋ฉ URL๋ ๊ฐ๊ณตํด์ผ ํ๋ ์๊ฐ์ด ์ฐพ์์์ต๋๋ค.
์ ์ฑ ์ ๋ฐ์ํ๋ค
์นด์นด์คํ์ด ์ฑ ์ ์ฑ ์ด ๋ณ๊ฒฝ๋๋ฉด์ OS ์๋ฆผ ์ผํฐ์ ์๋ฆผํผ๋์์ ๋ฉ์์ง์ ๋๋ฉ ๋์์ด ์๋ก ๋ฌ๋ผ์ผ ํ์ต๋๋ค. OS ์๋ฆผ ์ผํฐ์์ ์ฑํธ์ ๋ฉ์์ง๋ฅผ ํด๋ฆญํ ๊ฒฝ์ฐ๋ ์นด์นด์คํ์ด ์ฑ์ด ์ด๋ฆฌ๊ณ ํน์ ํ๋ฆ์ ๊ฑฐ์น ํ ์๋น์ค๋ก ๋๋ฉ ํฉ๋๋ค. ํ์ง๋ง ์๋ฆผํผ๋์์ ๋ฉ์์ง๋ฅผ ํด๋ฆญํ ๊ฒฝ์ฐ๋ ์นด์นด์คํ์ด ์ฑ ๋ด๋ถ์์์ ๋์์ด๊ธฐ ๋๋ฌธ์ ํน์ ํ๋ฆ์ ๊ฑฐ์น์ง ์์์ผ ํฉ๋๋ค.
์ ์ฑ ์ ๋ฐ์ํ๊ธฐ ์ํด์๋ ๋ฉ์์ง์ ๋๋ฉ URL์์ ํน์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๊ฑฐํ๋ฉด ๋ฉ๋๋ค. ์๋์ ๊ฐ์ด OS ์๋ฆผ ์ผํฐ์ ๋ง์ถฐ์ง ๋ฉ์์ง ๋๋ฉ URL์์ base ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๊ฑฐํ๋ฉด ๋๋๋ฐ์. ์๋ฆผํผ๋์ ๋๋ฉ URL์ ๊ฐ๊ณตํ๋ ๋ก์ง์ ์ถ๊ฐํ ๊ทธ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.
- OS ์๋ฆผ ์ผํฐ์์์ ๋ฉ์์ง ๋๋ฉ URL:
kakaopay://payweb?base=home&min_version=2.22.1
- ์๋ฆผํผ๋์์์ ๋ฉ์์ง ๋๋ฉ URL:
kakaopay://payweb?min_version=2.22.1
์ฅ์ ๊ฐ ๋ฐ์ํ๋ค
์๋ฆผํผ๋์ URL ์ฌ์ฒ๋ฆฌ ๊ธฐ๋ฅ์ ๋ฐฐํฌํ๊ณ ๋ช ์๊ฐ ํ, ๋ด๋ถ ํฌ๋ฃจ ์ฑ๋์ ํตํด ์๋ฆผํผ๋๊ฐ ์ด์ํ๋ค๋ ์ ๋ณด๋ฅผ ๋ฐ์์ต๋๋ค. ์ ๋ณด์ ๋ฐ๋ฅด๋ฉด ์๋ฆผํผ๋์์ ํน์ ๋ฉ์์ง์ ๋๋ฉ์ด ์ ๋๋ก ๋์ํ์ง ์๊ณ ์์์ต๋๋ค.
ํด๋น ๊ณ์ ์ API ์๋ต์ ํ์ธํด ๋ณด๋ ๋ฉ์์ง์ ๋๋ฉ URL์ด ์ด์ํ์ต๋๋ค. ์ด ํ์์ ํน์ ๋ฉ์์ง์์๋ง ๋ฐ์ํ๋๋ฐ์. ์ฒ์์๋ ํด๋น ๋ฉ์์ง๊ฐ ๋๋ฉ URL์ด ์๋ชป๋ ์ํ๋ก ์ ์ฅ๋ ๊ฒ์ ์๋๊น ์์ฌํ์ต๋๋ค. ํ์ง๋ง ์๋ฆผํผ๋ DB๋ฅผ ์ดํด๋ณด๋ ๋ฐ์ดํฐ ์์๋ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค.
- API ์๋ต ๋ด ๋ฉ์์ง์ ๋๋ฉ URL:
kakaopay:?min_version=2.22.1&data=(์๋ต)
- DB์ ์ ์ฅ๋ ๋ฉ์์ง์ ๋๋ฉ URL:
kakaopay://payweb_tab?min_version=2.22.1&data=(์๋ต)
- => API ์๋ต์ ๋ด๊ธด ๋ฉ์์ง์ ๋๋ฉ URL์ ๊ฒฝ์ฐ
//payweb_tab
์ ๋ณด๊ฐ ์ฌ๋ผ์ก์ต๋๋ค.
๋ฐ์ดํฐ ์์ ๋ฌธ์ ๊ฐ ์๋ค๋ ๊ฒ์ ์์ ๋ฐฐํฌํ ๊ธฐ๋ฅ์ ๋ฌธ์ ๊ฐ ์์์ ์๋ฏธํ์ต๋๋ค. ๊ทธ๋์ ์์ ๋ฐฐํฌํ ๊ธฐ๋ฅ์ ๋กค๋ฐฑํ๋๋ ๋คํํ๋ ๋ ์ด์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์์ต๋๋ค.
์น: ๋ฌด์์ด ๋ฌธ์ ์๋๊ฐ
๋ฐฐํฌํ ๊ธฐ๋ฅ์ ๋ฌธ์ ๊ฐ ์๋ค๋ ์ ์ ์ธ์งํ์ ๋ ๋ชน์ ๋นํฉ์ค๋ฌ์ ์ต๋๋ค. QA๋ ์งํํ๊ณ ์นด๋๋ฆฌ ์๋ต๋ ํ์ธํ๋ ๋ฑ ์ฌ๋ฌ ๋ฐฉ๋ฉด์ผ๋ก ๊ฒ์ฆ์ ์งํํ๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ฅ์ ๋ํ ํ์ ์ด ์์์ต๋๋ค. ๊ทธ๋์ ์ด ์ํฉ์ด ๋ฏฟ๊ธฐ์ง ์์๋๋ฐ์. ์ง์ ํ๊ณ ์์ธ์ ๋ถ์ํ๊ธฐ ์์ํ์ ๋๋ผ์ด ์ฌ์ค๋ค์ด ๋ณด์ด๊ธฐ ์์ํ์ต๋๋ค.
์ถ๊ฐํ ์ฝ๋๋ฅผ ์ดํด๋ณด์
private fun String.removeBaseParameter(): String =
UriComponentsBuilder.fromUri(URI(this))
.replaceQueryParam("base", null)
.build()
.toUriString()
์์ ์ฝ๋๊ฐ ๋ฐ๋ก, ๋น์ ์ถ๊ฐํ ์ฝํ๋ฆฐ ํ์ฅํจ์์
๋๋ค. Spring ํ๋ ์์ํฌ๊ฐ ์ ๊ณตํ๋ UriComponentsBuilder
ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ URL ๋ฌธ์์ด์์ ํน์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๊ฑฐํ๊ณ ์์ต๋๋ค. ์ฌ๋ฌ๋ถ์ ์ด ์ฝ๋์์ ๋ฌธ์ ์ ์ด ๋ฌด์์ธ์ง ๋ณด์ด์๋์?
์ด ํ์ฅํจ์๋ ์ปดํ์ผ๋ ์ ๋๊ณ ํน์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๊ฑฐํ๋ ๋์๋ ์ ์ํํฉ๋๋ค. ๊ทธ๋์ QA๋ฅผ ๋น๋กฏํ ์ฌ๋ฌ ๊ฒ์ฆ๋ ๋ฌธ์ ์์ด ํต๊ณผํ์ต๋๋ค. ํ์ง๋ง ์์ ์ฅ์ ์ํฉ์์ ๋ณด์๋ฏ ํน์ URL์ด ์ฃผ์ด์ง๋ฉด ์ด์ํ๊ฒ ๋์ํ๊ณ ์์ต๋๋ค.
๋น์์ ์ํฉ์ ํ ์คํธ ์ฝ๋๋ก ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค.
@Test
fun test1() { // ๋น์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์๋ ์ผ์ด์ค
val actual = "kakaopay://payweb?base=home&min_version=2.22.1".removeBaseParameter()
val expected = "kakaopay://payweb?min_version=2.22.1"
actual shouldBe expected
}
@Test
fun test2() { // ๋น์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ์ผ์ด์ค
val actual = "kakaopay://payweb_tab?base=home&min_version=2.22.1".removeBaseParameter()
val expected = "kakaopay://payweb_tab?min_version=2.22.1"
actual shouldBe expected
}
์์์ ํ
์คํธ๋ฅผ ํต๊ณผํ์ง ๋ชปํ URL์ด ๋ฐ๋ก ๋น์ ๋ฌธ์ ๋ฅผ ์ผ์ผํจ URL์
๋๋ค. ์ด URL์ ํ
์คํธ ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด, ํน์ ํ๋ผ๋ฏธํฐ๋ฟ๋ง ์๋๋ผ URL์ ์ฃผ์ ์์๊น์ง ์ ๊ฑฐ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค. payweb_tab
์ ๋ณด๋ ์ด๋๋ก ์ฌ๋ผ์ง ๊ฑธ๊น์?
์ฌ๋ผ์ง ์ ๋ณด๋ฅผ ์ฐพ์๋ณด์
์์ ๋น๊ตํ ๋ ๋ฌธ์์ด์ ๋ํด UriComponentsBuilder#fromUri
์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋์ ๋ฐํ ๊ฐ์ ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
์ ์ ์ผ์ด์ค์ ๋ฌ๋ฆฌ ๋น์ ์ ์ผ์ด์ค์ host
๋ณ์๊ฐ ๋น์ด ์์ต๋๋ค. ์ ์ ์ผ์ด์ค์ host
๋ณ์์ payweb
์ด ์ ์ฅ๋ ๊ฒ์ ๋ณด๋ฉด, ๋น์ ์ ์ผ์ด์ค์ host
๋ณ์์๋ ๋์ผํ ์์น์ payweb_tab
์ด ์ ์ฅ๋์ด์ผ ํ ๊ฒ ๊ฐ์๋ฐ์. ์ด์งธ์ host
๋ณ์์ payweb_tab
์ ๋ณด๊ฐ ๋ด๊ธฐ์ง ๋ชปํ ๊ฑธ๊น์?
UriComponentsBuilder#fromUri
๋ฉ์๋์์ host
๋ณ์์ ๋ฌด์์ ์ ์ฅํ๋์ง ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
UriComponentsBuilder#fromUri
์์ ํธ์ถํ๋ UriComponentsBuilder#uri
๋ฅผ ๋ฐ๋ผ๊ฐ ๋ณด๋ฉด host
๋ณ์์ ๋ฌด์์ด ์ ์ฅ๋๋์ง ๋ณผ ์ ์์ต๋๋ค. ์ธ์๋ก ์ ๋ฌ๋ URI
์ธ์คํด์ค์ host
๋ณ์๋ฅผ ๋๊ฒจ๋ฐ์ ์ ์ฅํ๊ณ ์๋ค์. ๊ทธ๋ ๋ค๋ฉด UriComponentsBuilder
์ธ์คํด์ค์ host
๋ณ์์ ๋ง์ฐฌ๊ฐ์ง๋ก URI
์ธ์คํด์ค์ host
๋ณ์๋ ๋น์ด ์์๊น์?
์ด์ด์ ์ธ์๋ก ์ ๋ฌ๋ URI
์ธ์คํด์ค๋ ํ์ธํด ๋ณด๊ฒ ์ต๋๋ค.
์ ์ ์ผ์ด์ค์ ๋ฌ๋ฆฌ ๋น์ ์ ์ผ์ด์ค์ host ๋ณ์๊ฐ ๋น์ด ์๋ค์. ๊ฒฐ๊ตญ UriComponentsBuilder
์ธ์คํด์ค๊ฐ ์๋ชป๋ URL์ ๋ง๋ค์ด๋ธ ๊ฒ์ URI ์ธ์คํด์ค์ host ๋ณ์๊ฐ ๋น์ด ์์๊ธฐ ๋๋ฌธ์ด์์ต๋๋ค. payweb_tab
์ ๋ณด๋ ์ด๋๋ก ์ฌ๋ผ์ง ๊ฑธ๊น์? URI ์ธ์คํด์ค๊ฐ payweb_tab
์ ๋ณด๋ฅผ ์ ์ฅํ์ง ์์ ๊ฑธ๊น์?
์ฌ๋ผ์ง ์ ๋ณด๋ ์ฌ๊ธฐ์
์ฌ์ค URI ์ธ์คํด์ค๋ payweb_tab
์ ๋ณด๋ฅผ ๋ฒ๋ฆฌ์ง ์์์ต๋๋ค. ๋น์ ์ ์ผ์ด์ค์ URI ์ธ์คํด์ค์ ๋ํด toString ๋ฉ์๋๋ฅผ ํธ์ถํด ๋ณด๋ฉด ์๋์ ๊ฐ์ด payweb_tab
์ ๋ณด๊ฐ ํฌํจ๋ URL์ด ๋ฐํ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋น์ ์ ์ผ์ด์ค์ URI ์ธ์คํด์ค ๋ณ์๋ฅผ ๋ค์ ํ์ธํด ๋ณด๋ฉด authority
๋ณ์์ ๊ฐ์ ์ ์ฅํ๊ณ ์๋ ๊ฒ๋ ๋ณผ ์ ์์ต๋๋ค.
์ฆ ์ฐ๋ฆฌ๊ฐ ์ฐพ์ ํค๋งค๋ payweb_tab
์ ๋ณด๋ URI ์ธ์คํด์ค์ ์์์ต๋๋ค. ๋จ์ง host
๋ณ์๊ฐ ์๋ authority
๋ณ์์๋ง ์ ์ฅํ๊ณ ์์ ๋ฟ์
๋๋ค.
์ฌ๋ผ์ง ์ ๋ณด์ ํ๋ฐฉ์ ์ฐพ์์ง๋ง ์ฌ์ ํ ๋ฌธ์ ์ ๋ฐ์ ์์ธ์ ์ค๋ฆฌ๋ฌด์ค์ ๋๋ค. ์ URI ์ธ์คํด์ค์ host ๋ณ์๋ ๋น์ด์๊ณ , ์ UriComponentsBuilder ์ธ์คํด์ค๋ authority ๋ณ์๋ฅผ ๋ฐ๋ผ๋ณด์ง ์์ ๊ฑธ๊น์? ์ ์ URI์ ๋ํด ์์๋ณธ ํ, ์ด๋ค์ ๋์ ๊ตฌ์กฐ๋ฅผ ํ์ธํด ๋ณด๋ฉฐ ๋ต์ ์ฐพ์๋ณด๊ฒ ์ต๋๋ค.
์ฌ์ด๊ฐ๋ฉฐ
์ดํ์ ๋ด์ฉ์ ์ดํดํ๊ธฐ ์ํด์๋ URI์ ๋ํด ์์๋ณผ ํ์๊ฐ ์์ต๋๋ค. ์ฌ๋ฌ๋ถ์ URI์ ๋ํด ์๊ณ ๊ณ์ ๊ฐ์? ํํ ์ฌ์ฉํ๋ URL๊ณผ๋ ๋ฌ๋ฆฌ URI๋ ์์ํ ์ ์๋๋ฐ์. ์ ์ URI์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค.
URI์ ๋ํด ์์๋ณด์
RFC 1630[1]์ ๋ฐ๋ฅด๋ฉด URI(Uniform Resource Identifier)๋ ์ธํฐ๋ท ์์์ ๊ณ ์ ์๋ณ์๋ฅผ ์๋ฏธํฉ๋๋ค. ๊ทธ์ ๋ฐํด ์ฐ๋ฆฌ์๊ฒ ์ต์ํ URL(Uniform Resource Locator)์ URI์ ํ์ ๊ฐ๋ ์ผ๋ก, ์ธํฐ๋ท ์์์ ์์น๋ฅผ ์๋ฏธํฉ๋๋ค.
๋๋ถ๋ถ์ ๊ฒฝ์ฐ๋ ์์น๋ง์ผ๋ก ์์์ ์๋ณํ ์ ์๊ธฐ ๋๋ฌธ์ URI์ URL์ด ๋์ผํฉ๋๋ค. ํ์ง๋ง ๊ฒ์๊ธ์ ํน์ ์น์ ์ ๊ฐ๋ฆฌํฌ ๋์ฒ๋ผ ์์น๋ง์ผ๋ก ์์์ ์๋ณํ ์ ์์ ๋๋ URI์ URL์ด ๋ค๋ฅธ ํํ๋ฅผ ๋ ๊ณค ํฉ๋๋ค.
- URI: https://tech.kakaopay.com/post/r2dbc-connection-pool-missing#์ปค๋ฅ์ -ํ์-๊ธฐ๋ํ๋-๋์
- URL: https://tech.kakaopay.com/post/r2dbc-connection-pool-missing
URI๋ฅผ ๊ตฌ์ฑํ๋ ์์๋ฅผ ๊ฐ๋จํ ํํํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
์ต์ํ ๋จ์ด๊ฐ ๋ณด์ด์ง ์์ผ์ ๊ฐ์? ์์ ๋ด์๋ host
์ authority
๋ URI์ ์ฃผ์ ์์์
๋๋ค. host๋ ์ธํฐ๋ท์์์ ์๋ณ ๊ฐ๋ฅํ ์ฃผ์(๋๋ฉ์ธ ์ฃผ์, IP ์ฃผ์)๋ฅผ ์๋ฏธํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ authority๋ ์ฃผ์์ ์ฌ์ฉ์ ์ ๋ณด ๋ฑ์ด ๊ฒฐํฉ๋ ์ ๊ทผ ๊ถํ์ ์๋ฏธํฉ๋๋ค.
ftc://rain-drop:password** **@kakaopay.com/data.txt
์ ์๋ก ๋ค์ด๋ณผ๊ฒ์. ์ฌ๊ธฐ์ authority
๋ ์ ๊ทผ ๊ถํ์ผ๋ก rain-drop:password@kakaopay.com
์ ๊ฐ๋ฆฌํค๊ณ , host๋ ์๋ณ ๊ฐ๋ฅํ ์ฃผ์ โkakaopay.comโ๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ฅ์ ๊ฐ ๋ฐ์ํ ๋ฉ์์ง์ kakaopay://payweb_tab?min_version=2.22.1
์ ์ด๋จ๊น์? authority
์ ๊ตฌ์ฑ ์์ ์ค ์ฌ์ฉ์ ์ ๋ณด์ port ์ ๋ณด๋ ์๋ต ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์, ์ฌ๊ธฐ์ authority
์ host
๋ ๋ชจ๋ payweb_tab
์ ๊ฐ๋ฆฌํต๋๋ค.
authority
์ host
์ ๊ด๊ณ๋ฅผ ๊ธฐ์ตํด ์ฃผ์ธ์. ๋ค๋ฅธ ๊ตฌ์ฑ์์๋ ์ด ๊ธ์์ ์ค์ํ์ง ์๊ธฐ์ ๋ค๋ฃจ์ง ์๊ฒ ์ต๋๋ค.
์ : ๋๊ตฌ์ ๋ฌธ์ ์ธ๊ฐ
์์ ์ฐ๋ฆฌ๋ ์ฌ๋ผ์ง ์ ๋ณด์ ํ๋ฐฉ์ ์ฐพ์ผ๋ฉฐ Java ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ๊ณตํ๋ java.net.URI
ํด๋์ค์ Spring ํ๋ ์์ํฌ๊ฐ ์ ๊ณตํ๋ UriComponentsBuilder
ํด๋์ค ์ฌ์ด์์ ๋ถํํ์์ ํ์ธํ์ต๋๋ค. URI ์ธ์คํด์ค๊ฐ ์ ์ฅํ๊ณ ์๋ ์ ๋ณด๊ฐ UriComponentsBuilder
์ธ์คํด์ค๋ก ์ ๋ฌ๋์ง ๋ชปํ ์ด ์ํฉ์ ์ด๋ป๊ฒ ๋ฐ๋ผ๋ด์ผ ํ ๊น์? ์๋์ ์๋ฌธ์ ์ ํ๋์ฉ ๋ค์ฌ๋ค๋ณด๋ฉฐ ๋์๊ฐ ๋ณด๊ฒ ์ต๋๋ค.
- ์ URI ์ธ์คํด์ค๋
host
๋ณ์๋ฅผ ๋น์๋๋๊ฐ? - ์
UriComponentsBuilder
์ธ์คํด์ค๋authority
๋ณ์๋ฅผ ๋ฐ๋ผ๋ณด์ง ์๋๊ฐ?
java.net.URI
ํด๋์ค๋ฅผ ๋ค์ฌ๋ค๋ณด๋ค
java.net.URI
ํด๋์ค๊ฐ host ๋ณ์๋ฅผ ์ด๋ป๊ฒ ์ ์ฅํ๊ณ ์๋์ง ํ์ธํ๊ธฐ ์ํด ์์ฑ์๋ฅผ ๋ค์ฌ๋ค๋ณด๊ฒ ์ต๋๋ค.
public URI(String str) throws URISyntaxException {
new Parser(str).parse(false);
}
URI.Parser
#parseURI.Parser
#parseHierarchicalURI.Parser
#parseAuthorityURI.Parser
#parseServerURI.Parser
#parseHostname- ...
URI ํด๋์ค์ ์์ฑ์๋ฅผ ๋ค์ฌ๋ค๋ณด๋ฉด Parser#parse
๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๋ชจ์ต์ด ๋ณด์
๋๋ค. Parser#parse
๋ฉ์๋๋ฅผ ๋ฐ๋ผ ๋ค์ด๊ฐ ๋ณด๋ฉด ์์ ํ๋ฆ๋๋ฅผ ์์ฑํ ์ ์๋๋ฐ์. ์ฌ๊ธฐ์ parseHostname
๋ฉ์๋๊ฐ ๋ฐ๋ก host ์์ญ์ ๊ตฌ๋ฌธ ๋ถ์์ ๋ด๋นํ๋ ๋ฉ์๋์
๋๋ค.
๋ค์์ parseHostname
๋ฉ์๋์ ๋ด์ฉ์
๋๋ค.
parseHostname
๋ฉ์๋์ ์ฃผ์์๋ host ์์ญ์ ๊ตฌ์ฑ ๊ท์น์ด ์ ํ์์ต๋๋ค. ์ด ์ฃผ์์ host ์์ญ์ด ์๋ฌธ์์ ์ซ์, ๊ทธ๋ฆฌ๊ณ -
๋ฌธ์๋ก ๊ตฌ์ฑ๋ ์ ์๋ค๊ณ ๋งํ๊ณ ์์ต๋๋ค. ๊ทธ๋ฐ๋ฐ ๋ญ๊ฐ ์ด์ํ์ง ์๋์?
kakaopay://payweb_tab?min_version=2.22.1
URL์ ๋ ์ฌ๋ ค ๋ณด๊ฒ ์ต๋๋ค. ์ด URL์ payweb_tab
์ -
๋ฌธ์๊ฐ ์๋ _
๋ฌธ์๋ฅผ ํฌํจํ๊ณ ์์ต๋๋ค. parseHostname
๊ฐ ๋ฐ๋ฅด๋ host
์์ญ์ ๊ตฌ์ฑ ๊ท์น์ ์ด๊ธฐ๊ณ ์๋ ๊ฒ์ธ๋ฐ์. ๊ฒฐ๊ตญ parseHostname
๋ฉ์๋๋ payweb_tab
์ host ๋ณ์์ ์ ์ฅํ์ง ์์ต๋๋ค.
kakaopay://payweb_tab?min_version=2.22.1
URL์ด ๊ท์น์ ์๋ฐฐํ๊ณ ์๋ค๋, ๋์ฒด ์ด๋ป๊ฒ ๋ ์ผ์ผ๊น์? ์ ๋น์ด ์ด ๋ฌธ์ ์ ์์์ ๊ท์น์ ์ด๊ธ๋ URL์ ๋ง๋ค์ด ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ด์์๊น์? URI ๋ฌธ๋ฒ์ ๋ํด ์กฐ์ฌํด ๋ดค์ต๋๋ค.
RFC ๋ฌธ์๋ฅผ ์ฐพ์๋ณด๋ค
Java Docs๋ฅผ ๋ณด๋ฉด ์๋์ ์ค๋ช
์์ java.net.URI
ํด๋์ค๊ฐ ๋ฐ๋ฅด๋ RFC ๋ฌธ์๋ฅผ ์ ์ ์์ต๋๋ค. RFC 2396[2]์ URI์ ๋ฌธ๋ฒ์ ์ฒ์ ์ ์ํ ๋ฌธ์์
๋๋ค. ์ด ๋ฌธ์๋ URI์ ๊ตฌ์ฑ์์๊ฐ ์ด๋ ํ ๊ท์น์ ๊ฐ์ ธ์ผ ํ๋์ง ์ ์ํ๊ณ ์์ต๋๋ค.
RFC 2396
Represents a Uniform Resource Identifier (URI) reference. Aside from some minor deviations noted below, an instance of this class represents a URI reference as defined by RFC 2396: Uniform Resource Identifiers (URI): Generic Syntax, amended by RFC 2732: Format for Literal IPv6 Addresses in URLs.
์ด ๋ฌธ์์ [RFC 2396. Section 3.2.2]์๋ ์๋์ ๊ฐ์ด host ์์ญ์ ๊ท์น์ด ์ ํ ์์ต๋๋ค. ํ์ง๋ง ์์ parseHostname
๋ฉ์๋์ ์ฃผ์์์ ๋ณธ ๊ฒ์ฒ๋ผ _
๋ฌธ์๋ ์ฐพ์๋ณผ ์ ์์ต๋๋ค.
RFC 2396
Hostnames take the form described in Section 3 of [RFC1034] and Section 2.1 of [RFC1123]: a sequence of domain labels separated by โ.โ, each domain label starting and ending with an alphanumeric character and possibly also containing โ-โ characters.
์ ๋ด์ฉ์ ๋ฐ๋ฅด๋ฉด ๊ฒฐ๊ตญ kakaopay://payweb_tab?min_version=2.22.1
์ RFC 2396์ ์๋ฐฐํ๊ณ ์์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด kakaopay://payweb_tab?min_version=2.22.1
์ ์ ๋ง ์๋ชป๋ URL์ผ๊น์? ํฅ๋ฏธ๋กญ๊ฒ๋ URI ๋ฌธ๋ฒ์ ๋ํ RFC ๋ฌธ์๋ ํ๋๊ฐ ๋ ์กด์ฌํฉ๋๋ค.
URI ํด๋์ค๊ฐ ๋ฐ๋ฅด๋ RFC 2396์ 1998๋ ์ ์์ฑ๋ ๋ฌธ์์ ๋๋ค. ์ด๋ URI ์ฐธ์กฐ ๋ฌธ๋ฒ์ด ์ฒ์ ์ ์๋๋๋ฐ์. ์๊ฐ์ด ํ๋ฌ 2005๋ ์ RFC 3986[3]์ด ๋ฑ์ฅํ์ต๋๋ค. ์ค๋๋ ํ์ค์ด ๋ RFC 3986์ RFC 2396์ ๋์ฒดํ์ฌ URI ๋ฌธ๋ฒ์ ์ฌ์ ์ํ๊ณ ์์ผ๋ฉฐ, ์ด์ ๊ด๋ จ๋ ๋ด์ฉ์ [RFC 3986. Introduction]์์ ์ฐพ์๋ณผ ์ ์์ต๋๋ค.
RFC 3986
This document obsoletes [RFC2396], which merged โUniform Resource Locatorsโ [RFC1738] and โRelative Uniform Resource Locatorsโ [RFC1808] in order to define a single, generic syntax for all URIs.
RFC 3986์ RFC 2396์์ ์ด๋ค ๋ถ๋ถ์ด ๋ฐ๋์์๊น์? ๋ฌธ์๋ฅผ ์ดํด๋ณด๋ฉด ์๋์ ๋ฌธ๊ตฌ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
RFC 3986
The server, hostport, hostname, domainlabel, toplabel, and alphanum rules have been removed.
RFC 3986์ ๋ ์ด์ RFC 2396์ ์ ์๋ ์ฌ๋ฌ ๊ท์น์ ๋ฐ๋ฅด์ง ์์ต๋๋ค. ์ ์ฝ์ ์์ ๋ ๋ฐฉํฅ์ ํํ๊ณ , RFC 2396๊ณผ ๋ฌ๋ฆฌ Hostname์ผ๋ก _
๋ฌธ์๋ฅผ ํ์ฉํ๊ณ ์์ต๋๋ค.
์ฆ kakaopay://payweb_tab?min_version=2.22.1
URL์ RFC 3986์ ๋ฐ๋ผ ๊ท์น์ ์งํค๊ณ ์์์ต๋๋ค. ์คํ๋ ค URI ํด๋์ค๊ฐ ์ง๊ธ์ ํ์ง๋ ์ ๋ฌธ๋ฒ์ ๋ฐ๋ฅด๋ฉฐ payweb_tab
์ host๋ก ์ธ์งํ์ง ๋ชปํ๊ณ ์์์ต๋๋ค. ๊ทธ๋ ๋ค๋ฉด UriComponentsBuilder
ํด๋์ค๋ ์ด๋จ๊น์?
UriComponentsBuilder
ํด๋์ค๋ฅผ ๋ค์ฌ๋ค๋ณด๋ค
UriComponentsBuilder
ํด๋์ค๋ RFC 3986์ ๋ฐ๋ฅด๊ณ ์์ต๋๋ค. ์ด ๋ด์ฉ์ ์ฝ๋์์ ํ์ธํ ์ ์๊ณ , ์๋์ [RFC 3986. appendix B]์ ๋์จ ์ ๊ท์์ ๋ฐ๋ผ URI๋ฅผ ํ์ฑํ๋ค๋ ์ ๋ ํ์ธํ ์ ์์ต๋๋ค.
RFC 3986
The following line is the regular expression for breaking-down a well-formed URI reference into its components.- ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
๊ทธ๋ ๋ค๋ฉด UriComponentsBuilder
๋ ์ java.net.URI
์ authority
๋ณ์๋ฅผ ๋ฐ๋ผ๋ณด์ง ์์์๊น์? URI ์ธ์คํด์ค์ host
๋ณ์๊ฐ ๋น์ด ์๋ค๋ฉด authority
๋ณ์๋ฅผ ๋ฐ๋ผ๋ดค์ผ๋ฉด ์ข์์ ํ
๋ฐ์. ์์ฝ๊ฒ๋ UriComponentsBuilder
ํด๋์ค, ๊ทธ๋ฆฌ๊ณ ์ด ํด๋์ค๊ฐ ์์ฑํ๋ UriComponents
ํด๋์ค๋ authority
๋ฅผ ๊ด๋ฆฌํ์ง ์๊ณ ์์ต๋๋ค.
์๋ UriComponents
์ getter
๋ฉ์๋ ๋ชฉ๋ก์ ๋ณด์๋ฉด ์ด๋ค์ด ๋ค๋ฃจ๋ URI์ ๊ตฌ์ฑ์์๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
authority
์ ์์์ธ userinfo
, host
, port
๋ฑ์ ๋ณด์ด์ง๋ง authority
์์ฒด๋ ๋ณด์ด์ง ์์ต๋๋ค. ์ฆ UriComponentsBuilder
๋ authority
๋ฅผ ๋ค๋ฃจ์ง ์๊ธฐ ๋๋ฌธ์ java.net.URI
์ authority
๋ณ์๋ฅผ ๋ฐ๋ผ๋ณด์ง ์์๊ณ , ์ด๋ก ์ธํด ์ ๋ณด์ ๋๋ฝ์ด ๋ฐ์ํ ๊ฒ์
๋๋ค.
๊ฒฐ: ์ด๋ป๊ฒ ํด๊ฒฐํ ์ ์๋๊ฐ
์๋ฌธ์ ๋ต์ ๋ด๋ฆฌ๋ค
์ฐ๋ฆฌ๋ ์ด ์ฅ์ ๊ฐ ์ ๋ฐ์ํ๋์ง ๋๋์ด ํด๋ต์ ์ฐพ์์ต๋๋ค. ์ด์ ๋ ์๋ฌธ์ ๋ํด ํ๋์ฉ ๋ต์ ์ ์ด๋ณด๋ฉฐ ์ ๋ฆฌํด ๋ณด๊ฒ ์ต๋๋ค.
Question. ์ URI
์ธ์คํด์ค๋ host
๋ณ์๋ฅผ ๋น์๋๋๊ฐ?
java.net.URI
ํด๋์ค๋ RFC 2396์ ๋ฐ๋ฅด๊ณ ์์ต๋๋ค. RFC 2396์ ์ํ๋ฉด host๋ ์๋ฌธ์, ์ซ์, -
๋ฌธ์๋ก ๊ตฌ์ฑ๋์ด์ผ ํฉ๋๋ค. ๊ทธ๋์ java.net.URI
ํด๋์ค๋ ๊ท์น์ ์ด๊ธ๋ payweb_tab
์ host์ ์ ์ฅํ์ง ์์์ต๋๋ค.
Question. RFC 2396์ ์๋ฐฐํ๋ค๋ฉด ์ฒ์๋ถํฐ URL์ด ์๋ชป๋ ๊ฒ ์๋๊ฐ?
URL์ด ์๋ชป๋ ๊ฒ์ ์๋๋๋ค. ์ค๋๋ ํ์ค์ด ๋ RFC 3986์์๋ host
์ ๊ท์น ์ ํ์ ํด์ ํ๊ธฐ ๋๋ฌธ์ payweb_tab
์ host
๊ฐ ๋ง์ต๋๋ค. ๋จ์ง java.net.URI
๊ฐ ํ์ง๋ RFC 2396์ ๋ฐ๋ฅด๊ณ ์๊ธฐ์ ๋ฐ์ํ ๋ฌธ์ ์
๋๋ค.
Question. ์ UriComponentsBuilder
์ธ์คํด์ค๋ authority
๋ณ์๋ฅผ ๋ฐ๋ผ๋ณด์ง ์๋๊ฐ?
UriComponentsBuilder
ํด๋์ค๋ userinfo
, host
, port
๋ฑ์ ๊ตฌ์ฑ์์๋ ๊ด๋ฆฌํ์ง๋ง authority
๋ฅผ ๋ค๋ฃจ์ง๋ ์์ต๋๋ค. ๋๋ฌธ์ UriComponentsBuilder#fromUri
๋ฉ์๋๋ ์ธ์๋ก ์ ๋ฌ๋ URI
์ธ์คํด์ค๋ก๋ถํฐ authority
๋ณ์๋ฅผ ๋ฐ๋ผ๋ณด์ง ์์ ๊ฒ์
๋๋ค.
Question. ๋๊ตฌ์ ์๋ชป์ธ๊ฐ?
ํจ๋ถ๋ก ๋งํ๊ธฐ ์ด๋ ต์ง๋ง, ๊ฐ์ธ์ ์ธ ์๊ฐ์ผ๋ก๋ UriComponentsBuilder#fromUri
์ ๋ฌธ์ ๋ผ๊ณ ์๊ฐํฉ๋๋ค. java.net.URI
๋ ํ์ง๋ RFC 2396์ ๋ฐ๋ฅผ ๋ฟ URI
ํ์ฑ์ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์ ๋ณด๋ฅผ ๋๋ฝํ์ง ์๊ณ authority
์ ์ ์ฅํ๊ณ ์๊ธฐ๋ ํฉ๋๋ค. ํ์ง๋ง UriComponentsBuilder
์ ๊ฒฝ์ฐ, authority
๋ฅผ ๊ด๋ฆฌํ์ง ์๊ณ ์์ต๋๋ค. URI
์ธ์คํด์ค์ host
๋ง์ ๋ฐ๋ผ๋ณด๊ณ ์๋ ๋ถ๋ถ, ๋ฐ๋ก ์ด๊ฒ์ด ๋ฌธ์ ์ ์์ธ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
fromUriString
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ค
๋ฌธ์ ๋ฐ์ ์์ธ์ ์ฐพ์์ผ๋, ์ด์ ํด๊ฒฐ์ฑ
์ ์์๋ณด๊ฒ ์ต๋๋ค. ์ฌ๋ฐ๊ฒ๋ UriComponentsBuilder#fromUri
์ ๋์์ UriComponentsBuilder
ํด๋์ค ์์ ์์ต๋๋ค. UriComponentsBuilder
ํด๋์ค๋ fromUriString
๋ฉ์๋๋ฅผ ์ ๊ณตํ๊ณ ์๋๋ฐ์.
์ด ๋ฉ์๋๋ฅผ ๋ค์ฌ๋ค๋ณด๋ฉด, ์ ๊ท์์ ๊ธฐ๋ฐํ์ฌ URI๋ฅผ ํ์ฑํ๊ณ ์์์ ๋ณผ ์ ์์ต๋๋ค. [RFC 3986. appendix B]์ ๋์จ ์ ๊ท์์ ๋ฐ๋ผ host ๋ฑ์ ๊ตฌ์ฑ์์๋ฅผ ํ์ฑํ๊ธฐ ๋๋ฌธ์ java.net.URI
์ ๋ฌ๋ฆฌ ์ ๋ณด๋ฅผ ๋๋ฝํ์ง ์์ต๋๋ค.
public class UriComponentsBuilder {
private static final String SCHEME_PATTERN = "([^:/?#]+):";
private static final String USERINFO_PATTERN = "([^@/]*)";
private static final String HOST_PATTERN = "([^/?#:]*)";
private static final String PORT_PATTERN = "(\\d*)";
private static final String PATH_PATTERN = "([^?#]*)";
private static final String QUERY_PATTERN = "([^#]*)";
private static final String LAST_PATTERN = "(.*)";
// Regex patterns that matches URIs. See RFC 3986, appendix B
private static final Pattern URI_PATTERN = Pattern.compile(
"^(" + SCHEME_PATTERN + ")?" + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN +
")?" + ")?" + PATH_PATTERN + "(\\?" + QUERY_PATTERN + ")?" + "(#" + LAST_PATTERN + ")?");
public static UriComponentsBuilder fromUriString(String uri) {
Assert.hasLength(uri, "'uri' must not be empty");
Matcher m = URI_PATTERN.matcher(uri);
if (m.matches()) {
UriComponentsBuilder builder = new UriComponentsBuilder();
builder.scheme(m.group(2));
builder.userInfo(m.group(5));
builder.host(m.group(6));
String port = m.group(8);
if (StringUtils.hasLength(port)) {
builder.port(Integer.parseInt(port));
}
builder.path(m.group(9));
builder.query(m.group(11));
builder.fragment(m.group(13));
return builder;
}
else {
throw new IllegalArgumentException("[" + uri + "] is not a valid URI");
}
}
...
}
์ฅ์ ๋น์ ์ถ๊ฐํ๋ ํ์ฅํจ์์ ๋ํด fromUriString
๋ฉ์๋๋ฅผ ์ฌ์ฉํ ๋ก ์์ ํ๊ณ ํ
์คํธ ์ฝ๋๋ฅผ ์คํํด ๋ดค์ต๋๋ค. fromUri
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๊ณผ ๋ฌ๋ฆฌ, ๋ชจ๋ ํ
์คํธ๊ฐ ํต๊ณผํ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
private fun String.removeBaseParameter(): String =
UriComponentsBuilder.fromUriString(this) // ์์ (fromUri -> fromUriString)
.replaceQueryParam("base", null)
.build()
.toUriString()
@Test
fun test1() {
val actual = "kakaopay://payweb?base=home&min_version=2.22.1".removeBaseParameter()
val expected = "kakaopay://payweb?min_version=2.22.1"
actual shouldBe expected
}
@Test
fun test2() {
val actual = "kakaopay://payweb_tab?base=home&min_version=2.22.1".removeBaseParameter()
val expected = "kakaopay://payweb_tab?min_version=2.22.1"
actual shouldBe expected
}
์ฌ๋ฐ ๋ฐฉ์ง์ ๊ธฐ์ฌํ๋ค.
์์ธ์ ๋ถ์ํ๊ณ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๋ค์, ํญ์ ๋ง์ง๋ง์๋ ์ฌ๋ฐ ๋ฐฉ์ง๋ฅผ ๊ณ ๋ฏผํ๊ณ ์์ต๋๋ค. ์ง๊ธ๊ป ์ฅ์ ๋ ์ฃผ๋ก ๊ฐ๋ฐ์ด๋ ๊ธฐํ์ ์ค์๋ก ๋ฐ์ํ์ต๋๋ค. ๊ทธ๋์ ํ ์คํธ ์ฝ๋๋ฅผ ๋ณด์ถฉํ๊ฑฐ๋ QA์ ๊ฒ์ฆ ์ผ์ด์ค๋ฅผ ์ถ๊ฐํ๋ ๋ฐฉํฅ์ผ๋ก ์ฌ๋ฐ ๋ฐฉ์ง๋ฅผ ํด์๋๋ฐ์. ์ด๋ฒ์ ๋ฐ์ํ ์ฅ์ ์ํฉ์ ์ข ๋ฌ๋์ต๋๋ค.
UriComponentsBuilder#fromUri
๋ฉ์๋์ ์ด๋ฐ ๋ฌธ์ ์ ์ด ์๋ค๋ ์ฌ์ค์ ๊ณผ์ฐ ์ผ๋ง๋ ๋ง์ ๊ฐ๋ฐ์๋ค์ด ์๊ณ ์์๊น์? ๋ด๋ถ ๊ตฌํ์ ๋ค์ฌ๋ค๋ณด์ง ์์๋ค๋ฉด ์ด ์ฌ์ค์ ๋ชจ๋ฅผ ๊ฒ๋๋ค. ์ฐ๋ฆฌ๋ ๋ด๋ถ ๊ตฌํ์ ๋ค์ฌ๋ค๋ณธ ํ์์ผ java.net.URI
ํด๋์ค์ UriComponentsBuilder
ํด๋์ค ์ฌ์ด์ ์ ๋ณด ๋๋ฝ์ ์์์ผ๋๊น์. ์ด๋ ๋ฏ ์ด๋ฒ ์ฅ์ ๋ ๊ฐ๋ฐ์์ ์ค์๊ฐ ์๋๋ผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ด๋ถ ๊ตฌํ์ ์ํด ๋ฐ์ํ๋ค๋ ์ ์์ ํ์์์ ์ฅ์ ์ํฉ๊ณผ ๋ฌ๋์ต๋๋ค.
๊ทธ๋์ ์ด ๋ด์ฉ์ ์ฌ๋ด ์ฑ๋์ ๊ณต์ ํ์ต๋๋ค. ์นด์นด์คํ์ด๊ฐ ๋ณด๋ค ์์ ํ ์๋น์ค๋ฅผ ์ ๊ณตํ ์ ์๋๋ก, ๋ง์ ํฌ๋ฃจ๋ค์ด ์ด ๋ฌธ์ ์ ์ ์ธ์งํ๊ณ UriComponentsBuilder
ํด๋์ค๋ฅผ ์ฌ์ฉํ ๋ ์ฃผ์ํ๊ธฐ๋ฅผ ๋ฐ๋์ต๋๋ค. ์ด ๋ด์ฉ์ ๊ฐ์ฌํ๊ฒ๋ ๋ง์ ๋ถ๋ค์ ๊ด์ฌ์ ๋ฐ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ํ์ฑ์ ๊ณต๊ฐํ์ ํฌ๋ฃจ๋ค์ ์ถ์ฒ์ผ๋ก ์นด์นด์คํ์ด ์ ์ฌ ์๋ํ๋ธ์ ์ปค์คํ
๋ฃฐ์ผ๋ก ๋ฑ๋ก๋ ์ ์์์ต๋๋ค.
๋ง์น๋ฉฐ
์ง๊ธ๊น์ง ์๋ฆผํผ๋ ์๋น์ค์์ ๋ฐ์ํ ์ฅ์ ์ํฉ์ ๋ํด ์์ธ๊ณผ ๋์์ ์ดํด๋ดค์ต๋๋ค. java.net.URI
ํด๋์ค์ UriComponentsBuilder
ํด๋์ค์ ๊ด๊ณ์ ๋ํด ๋ค์ฌ๋ค๋ณผ ์ ์์ด์ ๋ป๊น์ ์๊ฐ์ด์๋๋ฐ์. ์ฌ๋ฌ๋ถ์ ์ด๋ ์
จ๋์?
์ ๋ ์๋ก์ด ์ฌ์ค์ ์๊ฒ ๋์ด ํฅ๋ฏธ๋ก์ด ์๊ฐ์ด๊ธฐ๋ ํ์ง๋ง ์์ฌ์์ด ๋ง์ด ๋จ๋ ์๊ฐ์ด๊ธฐ๋ ํ์ต๋๋ค. ์ฌ์ค ๊ธฐ๋ฅ์ ๊ตฌํํ ๋น์ fromUriString
๋ฉ์๋์ ์กด์ฌ๋ฅผ ์๊ณ ์์์ต๋๋ค. ๋ค๋ง fromUriString
๋ฉ์๋์ fromUri
๋ฉ์๋๊ฐ ์ธ์ ํ์
์ ๋ค์ํ ๋ฐ๊ธฐ ์ํด ์กด์ฌํ๋ค๊ณ ์๊ฐํ์ต๋๋ค. ์ด๋ฐ ๋จ์ํ ์๊ฐ ๋๋ฌธ์ ๋ด๋ถ ๋์์ ๋ชจ๋ฆ์๋ fromUri
๋ฉ์๋๋ฅผ ์ ํํ๋๋ฐ์. String
๋ฌธ์์ด์ ๊ทธ๋๋ก ์ธ์๋ก ๋๊ธฐ๋ ๊ฒ๋ณด๋จ URI
ํด๋์ค๋ก ํ ๋ฒ ๊ฐ์ธ์ ์ ๋ฌํ๋ ๊ฒ์ด ๊ตฌ๋ฌธ ๋ถ์์ ์์ด์ ์์ ํ ๊ฒ์ด๋ผ๊ณ ํ๋จํ์ต๋๋ค. ํ์ง๋ง ์ ์๋์ ๋ฌ๋ฆฌ ๋ด๋ถ ๋์์ ๊ทธ๋ ์ง ์์๊ณ , ๊ทธ๋ก ์ธํด ์ฅ์ ๊ฐ ๋ฐ์ํ์ต๋๋ค.
๋ค์ ๊ทธ๋๋ก ๋๋์๊ฐ๋ค๋ฉด ์ด ๋ฌธ์ ๋ฅผ ๋ง์ ์ ์์์๊น์? ํ์ ํ๊ธฐ ์ด๋ ต์ง๋ง, ๊ทธ๋๋ ํ์ฌ์ ๋ฏธ๋๋ ๋ค๋ฆ
๋๋ค. ์ด๋ฒ ๊ฒฝํ์์ ๋ง์ ๊ฒ์ ํ์ตํ๊ณ ์๊ฐํ ์ ์์์ต๋๋ค. java.net.URI
ํด๋์ค์ UriComponentsBuilder
ํด๋์ค์ ๊ด๊ณ์ ๋ํ ์ฌ์ค๋ ์ ์ ์์๊ณ , ํ์ ๋น์ฐํ๋ฏ์ด ์ฌ์ฉํด ์ค๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ํด ์กฐ์ฌ์ค๋ฌ์ด ํ๋๋ฅผ ๊ฐ์ง ์ ์์์ต๋๋ค. ์ฌ๋ฌ๋ถ์ ์ด๋ ์
จ๋์? ์ ๊ฐ ๊ฒฝํํ ์ด ๋ด์ฉ์ด ์ฌ๋ฌ๋ถ๊ป๋ ๋์ ๋์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค.
์ง๊ธ๊น์ง ๊ธด ์๊ฐ ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.