๐ ๊ฒฐ๋ก
์ ๋ชฉ์ ์๋ฌ๋ ์๋ฒ์ Interceptor์์ ๋ฐํ๋๋ ์๋ฌ์ด๋ค. ๋์ ๊ฒฝ์ฐ '๊ฐ์ token์ ๊ฐ์ง ์ฌ์ฉ์ ๊ฐ socket ํต์ ์ ํ๊ณ ์' ํ์ฌ Interceptor์์ throwerrorํ ์ผ์ด์ค์๋ค. ํ ์ฌ์ฉ์๊ฐ STOMP Message๋ฅผ Publishํ์์ผ๋ ๋ณธ์ธ์ ์ ์ธํ Subscriber๊ฐ ์์๊ธฐ์ ์๋ฒ์ Interceptor์์ error๋ก throw๋ ๊ฒ์ด๋ค. ์์ผ ํต์ ์ค ์ ์๋ฌ๋ฅผ ๊ฒช๋๋ค๋ฉด ์๋ฒ Interceptor์์ ์ฒดํฌํ๋ ๋ฌด์ธ๊ฐ(!)๋ฅผ ํ์ธํด ๋ณด๋ฉด ๋๋ฒ๊น ํ ์ ์์ ๊ฒ์ด๋ค.
์๋ฒ ๋ก์ง
์๋ฒ์์๋ STOMP ๋ฉ์์ง๋ฅผ ํด๋ผ์ด์ธํธ๊ฐ Publishingํ๋ฉด ๋ฉ์์ง ํค๋์ token์ ํตํด ์ด๋ค ์ ์ ๊ฐ ๋ณด๋๋์ง ์๋ณํ๋ค. ์ด๋ ๊ฒ ์๋ณํ ํ์ Publisher ์ธ ๋ฉ์์ง๋ฅผ ์์ ํ Subscriber๋ฅผ ์ฐพ๊ฒ ๋๋ค. ์ฌ๊ธฐ์ ์ด๋ค Subscriber๋ ์๋ ๊ฒฝ์ฐ .orElseThrow() ํจ์๋ก Exception๋ฐ์ํ๋ค.
...
private GameMemberEssentialDTO findOtherUser(Set<GameMemberEssentialDTO> cachedUser, String nickname) {
return cachedUser.stream()
.filter(dto -> !dto.nickname().equals(nickname))
.findFirst()
.orElseThrow(MemberNotFoundException::new);
}
...
if (destinationUrl.equals("/app/" + roomCode + "/tetris")) {
// Sender๊ฐ ์๋ ์ ์ ์ฐพ๊ธฐ
GameMemberEssentialDTO otherUser = findOtherUser(cachedUser, nickname);
accessor.setHeader("otherUser", otherUser.nickname());
}
...
GameMemberEssentialDTO๋ฅผ ๋ณด๋ฉด, nickname์ด ๊ฐ์ ๊ฒฝ์ฐ .filter() ํ์ฌ ๊ฑฐ๋ฅธ ํ์ .findFirst()๋ก ๊ฐ์ฅ ์์ ์๋ Subscriber๋ฅผ ์ฐพ๊ฒ ๋๋ค. ๋ชป ์ฐพ์ผ๋ฉด .orElseThrow()๋ก Exception ์ฒ๋ฆฌ๊ฐ ๋๋ ๊ฒ์ด๋ค.
์ง๊ธ ์๊ฐํด๋ณด๋ฉด ๋งค์ฐ ๋งค์ฐ ์๋ช ํ ์๋ฌ์ด์ง๋ง, ์ด ์๋ฌ์ ์์ธ์ ์ฐพ๋ ๊ฒ์ด ๊ทธ๋ฆฌ ๊ฐ๋จํ์ง ์์๋ค. ์๋ํ๋ฉด, ๋ฐฑ์๋ ํํธ์์ Interceptor๋ฅผ ์ถ๊ฐํ๋ฉฐ ์ฃผ์์ UUID๋ฅผ ํฌํจ์ํค๋ ์์ ์ด ๋์์ ์ด๋ฃจ์ด์ก๊ณ , ํ๋ก ํธ์๋ ํํธ์์๋ ์ด API์ ๋ง์ถฐ ์์ ์ด ์ด๋ฃจ์ด์ก๊ธฐ ๋๋ฌธ์ด๋ค. ๋ณ์ธ์ด ๋ง์ผ๋ ์ด๋ค ๊ฒ ๋ฌธ์ ์ผ์ง ๊ฐ์ด ์ ์๋ค.
๐ ๋ฒ๊ทธ์ ์์ธ์ ๋ฐ๊ฒฌํ๊ธฐ๊น์ง์ ๊ณผ์
0. ์ ๋๋ ์์ผ ํต์ !
๊ธฐ์กด์ STOMP ๋ฉ์์ง๋ฅผ ์ฃผ๊ณ ๋ฐ๊ธฐ ์ํด Publishing, Subcribing ํ๋ ์ฃผ์์๋ {roomCode}์ ๊ดํ ์ ๋ณด๊ฐ ์์๋ค. ๋จ์ํ '/user/queue/tetris'์ ๊ฐ์ด ์ค์ ๋์ด ์์๋ค. ์ด์ ๋ค๋ฅธ ๋ฐฉ์์ ํ๋ ์ดํ๊ณ ์๋๋ผ๋ Publishing ํ๋ ์ ๋ณด๋ฅผ ๋ฐ๊ฒ ๋๋ ๋ฌธ์ ๊ฐ ์์๋ค. ์ค๊ฐ๋ฐํ๋ฅผ ์ํด์ ๊ฐ๋จํ๊ฒ ๊ตฌํํ์๋ ๊ฒ์ผ๋ก, ๋ฐฉ๋ณ๋ก ๋ถ๋ฆฌํ์ฌ Pub, Sub ๋๋๋ก ์์ ์์ ์ด ํ์ํ ์ํฉ์ด์๋ค.
- Interceptor๊ฐ ์์
- Pub, Sub ์ฃผ์์ {roomCode}๊ฐ ํฌํจ๋์ด ์์ง ์์
- arc ๋ธ๋ผ์ฐ์ ์คํ๋ฆฟ ๋ทฐ๋ก ํ ์คํธ ์ค ์ ์ ์๋
1. ์๋ฌ๋ฅผ ๋ง๋๊ฒ ๋ ์ํฉ
๋ฐฉ๋ณ๋ก Pub, Sub ๋ถ๋ฆฌ๋ฅผ ์ํด ๋ฐฑ์๋ ๋จ์์๋ ์ด ์์ ๋ถํฐ Interceptor๋ฅผ ๋์ ํ์๋ค. ํ๋ก ํธ์๋ ๋จ์์๋ ์ด ์์ ๋ถํฐ Server์๊ฒ ๋ฐ์ UUID๋ฅผ ํด๋ผ์ด์ธํธ session storage์ ์ ์ฅํ์ฌ STOMP ๊ตฌ๋ ์ฃผ์์ {roomCode}๋ฅผ ์ถ๊ฐํ์๋ค.
์ด๋ ๊ฒ ์ธํ ์ ๋ง์น ํ์ ์๋ฒ ํต์ ํ ์คํธ ๊ฒฐ๊ณผ 'Failed to send message to ExecutorSubscribableChannel[clientInboundChannel]'๋ฅผ ๋ง๋๊ฒ ๋์๋ค.
- Interceptor๊ฐ ์์
- Pub, Sub ์ฃผ์์ {roomCode}๊ฐ ํฌํจ๋์ด ์์ง ์์
- arc ๋ธ๋ผ์ฐ์ ์คํ๋ฆฟ ๋ทฐ๋ก ํ ์คํธ ์ค ์๋ฌ ๋ฐ์
2. ์๋ํฌ์ธํธ, ๋ฉ์์ง ํ์ ๋ฑ ์ฌํ์ธ
๋ฐฑ์๋ ํํธ์์๋ Interceptor, Pub, Sub ์ฃผ์ ๋ฑ์, ํ๋ก ํธ์๋ ํํธ์์๋ roomCode, Pub, Sub ์ฃผ์ ๋ฑ์ ๋ค์ ์ฌํ์ธํ๋ค. ์ด๋๊น์ง๋ง ํด๋ token์์๋ ๋ฌธ์ ๊ฐ ์์ ๊ฒ์ด๋ผ ์๊ฐํ๋ค. ์๋ํ๋ฉด ์คํ๋ฆฟ ๋ทฐ๋ก ๋๋์ด ๊ฐ ์ฐฝ์์ ๋ฐ๋ก ๋ก๊ทธ์ธ์ ํ๊ธฐ์ token ๊ฐ์ด ๋ค๋ฅผ ๊ฒ์ด๋ผ ์ถ์ธกํ๊ธฐ ๋๋ฌธ์ด๋ค.
3. ๋ฐฑ์๋ ํํธ์ ํจ๊ป ์คํ ํ๊ฒฝ์ ํต์ ํ๋ฉฐ ํ ์คํธ ๐ค
AS-IS | TO-BE |
- ํ๋ก ํธ์๋ ํด๋ผ์ด์ธํธ + ๋ฐฐํฌ ์๋ฒ - ๋ฐฑ์๋ ํด๋ผ์ด์ธํธ + ๋ก์ปฌ ์๋ฒ |
- ํ๋ก ํธ์๋ ํด๋ผ์ด์ธํธ + ๋ฐฐํฌ ์๋ฒ - ํ๋ก ํธ์๋ ํด๋ผ์ด์ธํธ + ๋ก์ปฌ ์๋ฒ |
ํ์์์๋ ์ด๋ค ์ชฝ์ด ๋ฌธ์ ์ธ์ง ๊ฐ์ด ์ ์กํ๋ ์ํฉ์ด๋ผ ํด๋ฆฌ์ธํธ ๋จ์ ํต์ผํ๊ณ ์๋ฒ๋ง ๋ฌ๋ฆฌ ์ฐ๊ฒฐํ์ฌ ํ ์คํธํด ๋ณด์๋ค. ์ฌ์ค ๋ฐฑ์๋์ ๋ฐฐํฌ ์๋ฒ์ ๋ก์ปฌ ์๋ฒ๋ ๋์ผํ ์ฝ๋๋ก ์๋ํ๊ธฐ์ ๊ธด๊ฐ๋ฏผ๊ฐ ํ ์ํ์์ ํ์ธํ์๋ค. ๊ฒฐ๊ณผ๋ ํต์ ์ด ๋์๋ค.
4. ์ํฌ ๋ธ๋ผ์ฐ์ ๋ฅผ ์์ฌ
๋ฐฑ์๋ ํํธ์ ์ด์์ฒด์ ๋ ์๋์ฐ์๋๋ฐ, ๋๋ ๋งฅ์ ์ฌ์ฉํ๊ณ ์์๋ค. ๊ทธ๋์ ์ฒ์์๋ ์ด์์ฒด์ ์ฐจ์ธ๊ฐ ์ถ์๋ค. ๊ทธ๋ฌ๋ ์ค ๋ธ๋ผ์ฐ์ ์ ์ฐจ์ด๊ฐ ์๋ ๊ฒ์ ์๊ฒ ๋์๋ค. ๋งฅ์์ ํฌ๋กฌ๋ธ๋ผ์ฐ์ + ์ํฌ๋ฆฟ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ๋ก ํ ์คํธํด๋ณด๋ ์ ์ ํต์ ํ์๋ค.
5. ๋ธ๋ผ์ฐ์ ๋ณ Stomp Header๋ฅผ ํ์ฑํ๋ ๊ฒ์ ์ํ ์ฐจ์ด?
์ํฌ ๋ธ๋ผ์ฐ์ ์์ ๋์ง ์๋ ์ด์ ๋ก ํ ํฐ์ ์ํ ๊ฒ์ด๋ผ๋ ํ๋จ์ด ๋ฐ๋ก ์์ง ์์๋ค. ์ฒ์์๋ Socket ํต์ ์ ํค๋๋ฅผ ํ์ฑ ํ์ฌ Server๋ก ๋ณด๋ผ ๋ ํ์ฑ ์ ํฌ๋กฌ ๋ธ๋ผ์ฐ์ ์ ๋ฐฉ์๊ณผ ์ฐจ์ด๊ฐ ์์ด์ ๊ทธ๋ฐ ๊ฒ์ธ ์ค ์์๋ค. ChatGPT์ ๋ฌผ์ด๋ดค์ ๋ ๊ทธ๋ด ์๋ ์๋ค๊ณ ํ์๊ธฐ ๋๋ฌธ์ด๋ค.
6. Fiddler
๊ตฌ์ฒด์ ์ผ๋ก ์ํฌ์ ํฌ๋กฌ์ด ์ด๋ป๊ฒ ๋ค๋ฅด๊ฒ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋์ง ํ์ธํ๊ณ ์ถ์๋ค. ๋คํธ์ํฌ ํจํท ์ฌ์ด์ฆ๋ฅผ ํ์ธํ๊ธฐ ์ํด์ ์ด์ ์ ์ค์นํด๋๋ Fiddler๋ฅผ ๋ค์ ์ฌ์ฉํด ๋ณด๊ธฐ๋ก ํ๋ค. Fiddler์์ Proxy ๋ชจ๋๋ก Server๋ก ๋ณด๋ด๋ ๋ชจ๋ ํจํท์ ํ์ธํ ์ ์๋ค.
ํ์ธ ๊ฒฐ๊ณผ, Message Pack์๋ ์ฐจ์ด๊ฐ ์์๋ค. Fiddler์์ ์๋ก์ด ์๋ฌ ์ฝ๋๋ฅผ ๋ฐ์ ์ ์์๋ค. ์ด๋ฏธ์ง ์ฐ์ธก๊ณผ ๊ฐ์ด arc ๋ธ๋ผ์ฐ์ ์์ ํต์ ํ ๊ฒฐ๊ณผ์๋ 'Reason: ProtocolError (03-EA)' ์๋ฌ๋ฅผ Client๋ก ๋ณด๋ด๋ ๊ฒ์ ํ์ธํ ์ ์์๋ค.
7. ์ธํฐ์ ํฐ
๋ฐฑ์๋ ํํธ์ ์ด๋ฅผ ๊ณต์ ํ์, Interceptor์์ ๊ฑธ๋ฆฌ๋ ๊ฒ์ผ ์๋ ์๊ฒ ๋ค๊ณ ํ์๋ค. ์ฌ์ง์ด Interceptor๋ { roomCode }๋ฅผ ์ฃผ์์ ์ฌ์ฉํ๋ฉฐ ์ถ๊ฐํ ๊ฒ์ด๊ธฐ์ ์ ๋ ฅ ํ๋ณด์๋ค. ์ฌ๋ฌ .throwError() ๋ฉ์จ๋ ์ค token์ ํ์ฉํ์ฌ nickname์ ์ฐพ์๋ด๋ ์ฝ๋๋ฅผ ๋ณด๋ฉฐ '์ค๋ง ๊ฐ์ ํ๋ ์ด์ด๋ก ์ธ์ํ๋๊ฐ?' ํ๋ ์๊ฐ์ด ๋ค์๋ค.
์ด๋ฅผ ํ ์คํธํด๋ณด๊ธฐ ์ํด ์ํฌ ๋ธ๋ผ์ฐ์ ์ ์คํ๋ฆฟ ๋ทฐ ์ํ์์ ๊ฐ๊ฐ์ ์ฐฝ์์ ๋ก๊ทธ์ธ์ ํ๊ณ token ๊ฐ์ ํ์ธํ์๋ค.
๊ฒฐ๊ณผ๋ ์ ๋ต์ด์๋ค. Arc ๋ธ๋ผ์ฐ์ ์์ ์ํฌ๋ฆฟ ๋ธ๋ผ์ฐ์ ๋ฅผ ์ผ์ ํ ์คํธํด๋ณด๋ ๋ค๋ฅธ token ๊ฐ์ด ์ ์ฅ๋๋ฉฐ ์ ์์ ์ผ๋ก ์์ผ ํต์ ์ด ๋์๋ค. ์ ๊ฟ์ Arc ๋ธ๋ผ์ฐ์ ๋ฅผ ํํ๋ ๊ฒ์ด๋ค. Token์ด ๊ฐ์์ ๋ฐ์ํ๋ ์๋ฌ์๋๋ฐ.. ๐ ํ๋ก ํธ์๋์์๋ ์ค๋ณต ๋ก๊ทธ์ธํ์ ๋์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ์ถ๊ฐํ๊ธฐ๋ก ํ์๋ค.
8. ๋ง๋ฌด๋ฆฌ
๊ธธ๊ณ ๊ธด ์์ฌ๊ณผ ๊ฒ์ฆ์ ๋์ผ๋ก ๋ช ํํ๊ฒ ์๋ฌ๊ฐ ๋ฐ์ํ๋ ์์ธ์ ์ ์ ์์๋ค. ๊ฐ์ค์ ์ธ์ฐ๊ณ , ์ด๋ฅผ ๊ฒ์ฆํ๊ณ , ํ ์คํธํ๊ณ , ๋ ๋ฐ๊ฒฌํ ์ฌ์ค์์ ๊ฐ์ค์ ์ธ์ฐ๊ณ , ๋ฐ๋ณต.. ์ด๋ฐ ๊ณผ์ ์์์ ๋ง์ด ์ฐพ์๋ณด๊ณ , ๋ฐฐ์ฐ๊ณ , ๊นจ๋ซ๋ ๊ฒ ๊ฐ๋ค. ๋ฟ๋ฏํ๋ค.