문제발생

로그인 창을 만드는 중에 비밀번호를 암호화 한다는 의미로 눈모양 버튼을 인풋창에 넣어놨다.

하지만 평상시에는 원하는 위치에 있어서 별 문제 없어 보였지만,

비밀번호를 입력하지 않으면 에러 메시지를 인풋창 아래에 출력하려고 하니 버튼 위치가 틀어져 버린다.

평상 시

에러메시지 출력

 


문제해결

문제의 원인은 버튼의 position 속성에 있었다.

.eye-button 태그에 CSS 속성을 position: absolute 로 설정해뒀다.

따라서 부모 태그의 크기에 따라 절대적인 위치가 달라지는데, 에러 메시지를 평소엔 숨겨뒀을땐 문제가 없는데,

에러 메시지를 출력할때는 눈에 보이니까 그때 위치가 틀어져버리는 문제였다.

그래서 아래의 에러메시지를 출력하는 span 태그를 외부로 따로 빼서 문제를 해결했다.

일단 이 HTML, JS의 구조 자체가 별로 좋아보이진 않기 때문에 더 좋은 방법을 찾아봐야겠다.

 

변경 전

변경 후

문제 발견

 

위 사진의 input 태그의 테두리 색을 바꾸려고 했다.

클릭했을 때만 input 태그의 테두리 색을 바꾸려면 가상 클래스를 이용하면 된다고 공부했다.

그런데 .input:focus 로 색을 바꿨는데도 아래처럼 왜 검은색일까?

input:focus {
    border: 1px solid var(--linkbrary-primary-color, #6D6AFE);
}

 


문제 해결

문제는 outline 속성의 기본값이 바꾼 테두리 색보다 커서 가려버려서 생긴 문제였다.

아래처럼 outline 속성에 none 값을 주면 해결 된다.

CSS 는 꾸준히 해서 익숙해지는 수 밖에 없는것 같다. 힘들구나...

input:focus {
	border: 1px solid var(--linkbrary-primary-color, #6D6AFE);
	outline: none;
}

 

문제 발견

외부 API 에서 데이터를 받아와서 호출하는 페이지를 만들려고 했다.

버튼을 누르기 전에는 아무것도 렌더링하지 않고, fetch 함수를 호출할 때 데이터를 렌더링하게 만들고 싶었다.

그림으로 나타내면 아래와 같다.

하지만 버튼을 한번 누르면 데이터가 렌더링 되지 않고 두번 이상 눌러야 렌더링 되는 문제가 발생했다.

 


문제 해결

fetch 함수가 promise 객체를 반환하는 함수이기 때문에 발생한 문제였다.

promise 객체는 비동기 처리를 위해 나온 객체이며 코드 실행 순서는 순서대로 진행하다가

비동기 함수(promise 객체를 반환하는 함수)가 실행되면 즉시 다음 코드로 실행 흐름이 넘어간 후 나중에 콜백이 실행된다.

console.log('Start');

fetch(url)
  .then((response) => response.json())
  .then((result) => { console.log("fetch"); });

console.log('End');

 

위의 코드는 동기 실행의 경우 아래처럼 출력 됐을 것이다.

 

  1. console.log("start") 출력
  2. fetch 함수를 실행하여 해당 url로 요청
  3. fetch의 응답값을 받고 then 메서드로 콜백 수행하여 consol.log("fetch") 출력
  4. console.log("End") 출력

하지만 비동기 실행의 경우 아래처럼 동작한다.

 

  1. console.log("start") 출력
  2. fetch 함수를 실행하여 해당 url로 요청
  3. console.log("End") 출력
  4. fetch의 응답값을 받고 then 메서드로 콜백 수행하여 console.log("fetch") 출력

변경 전

const url = "https://api-blue-archive.vercel.app/api/characters?page=2";
const targetArea = document.querySelector('.targetArea');
const imageArea = document.querySelector('.imageArea');
const btn = document.querySelector('.magicBtn');

let bindedData = {};

getData = function () {
    fetch(url, {
        mode: 'cors'})
        .then((response) => response.json())
        .then((data) => {
            console.log("fetch finished");
            return bindedData = data.data;
        });
    imageArea.innerHTML = '';
    console.log("rendering start");
    console.log(bindedData);
    for (let i = 0; i < 20; i++) {
        const student = document.createElement('div');
        const name = document.createElement('div');
        name.textContent = bindedData[i].name;
        student.append(name);
        const image = document.createElement('img');
        image.setAttribute('src',bindedData[i].photoUrl);
        student.append(image);
        imageArea.append(student);
    }
}

btn.addEventListener('click', getData);

콘솔창은 아래와 같다. (버튼 두번 눌러야 원하는 응답이 온다. 빨간 줄 기준으로 1번째 2번째 클릭 구분)

 

변경 후

const url = "https://api-blue-archive.vercel.app/api/characters?page=2";
const targetArea = document.querySelector('.targetArea');
const imageArea = document.querySelector('.imageArea');
const btn = document.querySelector('.magicBtn');

let bindedData = {};

getData = function () {
    fetch(url, {
        mode: 'cors'})
        .then((response) => response.json())
        .then((data) => {
            console.log("fetch finished");
            imageArea.innerHTML = '';
            bindedData = data.data;
            
            console.log("rendering start");
            console.log(bindedData);
            for (let i = 0; i < 20; i++) {
                const student = document.createElement('div');
                const name = document.createElement('div');
                name.textContent = bindedData[i].name;
                student.append(name);
                const image = document.createElement('img');
                image.setAttribute('src',bindedData[i].photoUrl);
                student.append(image);
                imageArea.append(student);
            }
        });
}

btn.addEventListener('click', getData);

콘솔창은 아래와 같다. (버튼 한번만 눌러도 원하는 응답을 받을 수 있다.)

 

+ Recent posts