| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- HashMap
- append
- JS 공백 처리
- rocky10
- 백준 2473번 세 용액 - java
- 백준 3190번
- 백준 14938번 서강그라운드
- StringTokenizer
- 프로그래머스 자바
- StringBuilder
- 코틀린기초
- 프로그래머스 java
- 백준 1043번 거짓말 - java 분리 집합
- toUpperCase
- 프로그래머스
- Rocky10에 Postgres13 설치하기 - VMware
- hash
- 수동직렬화
- 톰캣 https 변경
- Rocky 10 - JDK 1.8.0 설치
- map
- kotlin
- HashSet
- mysql hy000 에러
- Stack
- Java
- dp
- replace()
- 백준 1541
- “application/x-www-form-urlencoded”
- Today
- Total
말하는 컴공감자의 텃밭
JS - 쿼리스트링 공백 -> '+' 변환 문제 본문
회원 가입을 마치고 사용자에게 토스트로 띄울 데이터를 담아 URL을 만들었는데 모든 공백이 '+' 로 변경되어 문제가 있었다.
url은 똑같은데 어디서는 +로 바뀌고,, 어디선 %20으로 처리되고.. 이해가 안갔는데~~
일단은 쿼리 스트링에서 값을 받아와야 하는 상황에 '감자 조아'면 '감자+조아' 이렇게 변환되어버리니, 얼른 고쳐보자.
var url = new URL(window.location.href);
문제의 결론은 말하자면 URL를 받아오면서 직렬화가 걸려서 공백이 '+'로 변환되고 있었다.
“application/x-www-form-urlencoded”
위 스펙에 일부 규칙 때문에 공백이 '+' 로 처리 되고 있었는데~ -> 관련자료
애플리케이션/x-www-form-urlencoded 대 애플리케이션/json: 어떤 것을 사용해야 할까요?
API 통신의 세계를 깊이 탐구하며 application/x-www-form-urlencoded와 application/json의 주요 차이를 살펴봅니다. 요청 본문에 적합한 형식을 선택하고 데이터 교환 전략을 최적화하는 방법을 배워보세요.
apidog.com
일단 현재 로직의 흐름은 다음과 같다.
1. 회원가입 후 일부 데이터를 포함한 쿼리스트링을 생성한다.
2. 해당하는 쿼리 스트링을 검증해서 해당 쿼리 스트링에 토스트 메세지 관련이 있는지 확인
3. 해당하는 값이 존재할 시 사용자에게 메세지 전송
4. 사용된 쿼리 데이터는 url에서 제거한다.
문제는 이 흐름속에서 발생을 하게 됐다.
url에서 사용한 데이터를 가공하는 과정에서 url을 받게 되었고, 그 과정에서 직렬화가 되어버렸다.
해결하기 위해서 자동으로 직렬화 되는부분으 수동으로 바꿔주었다.
기존 공백 처리는 %20 을 사용했기에 통일하기 위함이다. 근데 공백은 왜 %20이야?-> 관련자료
물론 서버나 받아오면서 단순하게 replaceAll()로 바꿔주는 방법도 있지만
직렬화 자동인게 뭔가 괘씸해서 찾아보게 되었다. 물론 +가 실제로 사용되는 경우도 대비하기 위함이긴 하다.
또한 (new URL(window.location.href) → url.searchParams.set(...) → url.toString()) 흐름이 정석이라서리..
그럼 이제 해결법을 보자
var url = new URL(window.location.href);
url.searchParams.delete("isTrue");
url.searchParams.delete("forMember");
// 공백 -> '+' 변환 문제로 수동 직렬화 추가.
const base = url.origin + url.pathname;
const query = Array.from(url.searchParams.entries())
.map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
.join("&");
history.replaceState({}, "", base + (query ? "?" + query : ""));
먼저 URL을 가져와주자. 저 문제 덩어리.

이런식으로 href로 변환하면서 규칙이 적용되어 있다.
따라서 이 url을 우리는 원하는 부분을 수정해주자. URL의 도메인 + 경로 부분만 따로 저장해주고
쿼리에 key/value 쌍으로 순회해서 encodeURIComponent을 직접 사용해 주었다.
encodeURIComponent 는 기본적으로 공백을 %20으로 처리한다. -> 관련자료
&, =, ? 등의 문자를 인코딩하여 URI가 제대로 해석되도록 도와줍니다.
이 함수는 주로 URI의 데이터를 안전하게 전송하기 위해 사용됩니다.
라네요~
그리고 마지막으로 쪼개진 우리 쿼리 데이터가 있다면 하나하나 붙여주고 url을 만들어 줍니다.
새로고침과 뒤로가기가 되면 안되므로 history.replaceState() 를 사용해 주었다.
내부 인자로는
- stateObj: 히스토리 상태 객체 (보통 {} 빈 객체)
- title: 거의 무시됨 (대부분 브라우저에서 안씀)
- url: 교체할 주소 (현재 페이지 기준 상대·절대 가능)
가 들어가게 된다.
이상 끝.