Feat: 단축 URL 생성 페이지 구현

This commit is contained in:
Gyubin-Han
2025-06-26 13:40:21 +09:00
parent cefe625759
commit 3911636661
2 changed files with 212 additions and 0 deletions

View File

@@ -0,0 +1,209 @@
<script>
const VALIDATE_URL="^((http|https):\\/\\/)?([a-z0-9-]{2,}\\.[a-z]{2,}|([0-9]{1,3}\\.){3}[0-9]{1,3})[\\w.\\/가-힣\\-\\ ?=&:]*";
// DOM 객체(요소) 체이닝 생성 클래스
class Element{
// 생성자
// type(string) : 요소(태그)의 종류 정의
constructor(type){
this.element=document.createElement(type);
this.element.eventList={}
}
// 하위에 DOM 객체(요소)를 추가하는 메소드
// child(Object(Element) || DOMObject) : 하위에 추가할 요소
append(child){
// child가 Object(Element)인 경우, 하위에 있는 element를 가져와 추가하고,
// 아닌 경우, child를 그대로 추가
this.element.append(child.element || child);
return this;
}
// 요소 내 html 코드를 직접 설정하는 메소드
html(html){
this.element.innerHTML=html;
return this;
}
// 요소에 표시할 text 값을 설정하는 메소드
text(text){
this.element.textContent=text;
return this;
}
// 요소에 class를 추가하는 메소드
addClass(name){
this.element.classList.add(name);
return this;
}
// 요소에 추가되어 있는 class를 제거하는 메소드
removeClass(name){
this.element.classList.remove(name);
return this;
}
// 링크 값을 설정하는 메소드
href(link){
this.element.href=link;
return this;
}
// id 값을 설정하는 메소드
id(value){
this.element.id=value;
return this;
}
// 요소의 속성 값을 설정하는 메소드
setAttr(name,value){
this.element.setAttribute(name,value);
return this;
}
// 요소에 설정되어 있는 속성을 제거하는 메소드
removeAttr(name){
this.element.removeAttribute(name);
return this;
}
// 이벤트 리스너를 추가하는 메소드
// type(string) : 감지될 이벤트 타입
// action(func) : 해당 이벤트가 발생했을 때, 처리될 이벤트 핸들러 함수
addEventListener(type,action){
this.element.eventList[type]=action;
this.element.addEventListener(type,action);
return this;
}
// 추가되어 있는 이벤트 리스너를 제거하는 메소드
// type(string) : 제거할 이벤트 타입
removeEventListener(type){
this.element.eventList[type]=null;
this.element.removeEventListener(type);
return this;
}
// 최종적으로 완성된 Element 객체를 DOM 요소 형태로 반환
get(){
return this.element;
}
}
// 단축 URL의 복사 버튼을 클릭하였을 때 동작되는 이벤트 함수
function clickBtnShortUrlCopy(shortId){
// 이 단축 URL의 사용자 내부 ID 값을 통하여, 단축 URL 값을 추출
// 주소를 복사할 범위 객체 생성
const range=document.createRange();
// 범위를 드래그할 객체 생성
const selection=window.getSelection();
// 드래그하기 전, 기존에 드래그 된 것은 제거
selection.removeAllRanges();
// 범위 지정
range.selectNodeContents(document.querySelector(".short-item[data-id='"+shortId+"'] .short-item-short-url"));
// 범위를 실제 드래그한 범위로 지정
selection.addRange(range);
// 사용자 클라이언트의 클립보드에 복사
document.execCommand("copy");
// 복사 후, 기존의 드래그 범위를 제거
selection.removeAllRanges();
// 사용자에게 성공적으로 복사되었음을 알림
alert("성공적으로 복사되었습니다!");
}
// 단축 URL 생성에 성공한 경우 동작하는 메소드
// 단축 URL의 정보를 사용자 화면에 출력
function createShortResultElement(data){
// 사용자의 접속 기본 정보를 추출
const userProtocol=window.location.protocol;
const userHost=window.location.host;
const shortUrl=userProtocol+"//"+userHost+"/"+data.shortUrl;
// 사용자 화면에 출력될 요소 생성 및 하위 요소 생성, 설정
var newRootElement=new Element("td");
newRootElement.text("단축되었습니다!");
newRootElement.append(
new Element("ul")
.append(new Element("li").text("원본 URL : "+data.originalUrl).addClass("short-item-original-url"))
.append(new Element("li").html("단축 URL : "+data.shortUrl+"<br>\n")
.append(new Element("span").html(shortUrl).addClass("short-item-short-url"))
.append(new Element("button").text("복사하기").addEventListener("click",function() { clickBtnShortUrlCopy(data.shortUrl); }))
)
.append(new Element("li").text("유효기간 : "+data.expiredAt))
)
newRootElement.setAttr("data-id",data.shortUrl);
newRootElement.addClass("short-item")
// 위에서 만들어진 요소를 실제 화면에 배치
document.querySelector("#short-list").append(new Element("tr").append(newRootElement).get());
}
// 단축 버튼을 클릭했을 때 동작되는 이벤트 함수
function clickBtnGenShort(){
// 이벤트(단축 버튼을 클릭)가 발생했을 당시 입력한 원본 URL 값을 가져옴.
var inputUrl=document.body.querySelector("input[type='text'][name='input_url']").value;
// 입력한 원본 URL이 올바른 형태의 URL인지 검증
if(!inputUrl.match(VALIDATE_URL)){
alert("잘못된 URL 값 입니다. 올바른 URL 값을 입력해주세요.");
return;
}
// 단축 URL 생성 요청 및 처리
var queryUrl="/short?url="+inputUrl;
fetch(queryUrl,{
method: "POST"
})
.then(response => {
if(!response.ok){
alert("통신 중에 오류가 발생했습니다.");
return;
}
return response.json();
})
.then(data => {
console.log(data);
// 응답된 데이터의 상태 코드가 success가 아니라면 알림창 출력
if(!data.status=="success"){
alert("URL 단축에 실패하였습니다. 다시 시도해주세요.");
return;
}
// 단축 URL 생성 성공
console.log("단축 성공 : "+data.shortUrl);
// 결과를 표시할 새 요소 생성
createShortResultElement(data);
})
.catch(error => {
console.error("에러 발생 : ",error);
});
}
</script>
<head>
<style>
#short-list{
width:100%;
margin:10px 0px;
padding:10px;
}
.short-item td{
padding: 7px;
}
.short-item td ul{
margin:3px;
}
</style>
</head>
<h3>HanGyub의 URL Shortener(단축기)</h3>
<table>
<tr>
정보 입력<br>
<input type="text" name="input_url" placeholder="단축할 원본 URL" size="50">
<button id="btn-gen-short">단축!</button>
</tr>
</table>
<br>
<table border="1" id="short-list">
</table>
<script>
document.querySelector("#btn-gen-short").addEventListener("click",function() { clickBtnGenShort(); });
</script>