팀 소개 사이트 만들기
어제부터 시작한 팀프로젝트!
첫 과제는 "팀소개 사이트 만들기"였다.
개강날이었던 어제는 간단하게 인사를 나누고 피그마를 활용해서 간단한 와이어프레임을 만들었다.
튜터님의 피드백
와이어프레임에 많은 기능들이 표현되지 않은것 같습니다. 지금 디자인 보다는 좀 더 많은 기능들을 넣고 개발 연습하는게 더 좋을거 같습니다.
기획 관련 메모들이 각자 구현 하는거지만 그래도 좀 더 자세히 적어서 문서를 좀 채워 주시면 좋겠습니다.
요구 사항도 좀 더 명확하게 문서에 기재 해주시면 좋을거 같습니다.
구현하는것 처음부터 완벽하지 않아도 됩니다.
문서, 팀원들과 소통으로 요구사항을 최대한 구현하고 구현 후에 팀원들과 소통하면서 코드를 개선할 방향을 찾아보면 좋겠습니다.
정말 맨~~ 처음에는 댓글 남기는 섹션이 없어서 스크립트 사용하는거라고는 모달이 전부였ㄷ..ㅎ
그래서 지금 초보입문자 수준에서 추가할 수 있는 부분이 뭔지 계속 생각하다가
왕초보강의에서 firebase를 배우기도 했으니 써먹어보자! 해서 급히 추가했다.
구현할 기능
여기서 내가 맡은 부분은 2번 모달창을 만드는부분이었다.
(사람1~사람5 버튼은 각자 맡은 부분을 구현하고 코드 합칠 때 클래스명을 수정하였다.)
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Modal</title>
<link rel="stylesheet" href="modal.css">
</head>
<body>
<button class="member_content">
사람1
</button>
<button class="member_content">
사람2
</button>
<button class="member_content">
사람3
</button>
<button class="member_content">
사람4
</button>
<button class="member_content">
사람5
</button>
<!-- 모달 시작 -->
<div id="modal_container">
<div id="modal" class="modal">
<span class="closeBtn">
<img src="images/close.png" alt="닫기버튼">
</span>
<div id="member_image"></div>
<h3 id="member_name"></h3>
<p id="member_age"></p>
<div id="member_info"></div>
</div>
</div>
<script src="modal.js"></script>
</body>
</html>
member_image
, member_name
, mamber_age
: 는 공간만 만들어두고 js에서 innerText
로 추가해주었다.member_content
에는 각 멤버별 소개를 넣어줄 공간으로 똑같이 innerText
작업을 해주었다.CSS
@charset "utf-8";
:root {
/* color */
--color-black: black;
--color-white: white;
--color-gray: #f6f6f6;
--color-green: #00D277;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
list-style: none;
}
.icon {
width: 80px;
height: 80px;
margin-right: 30px;
}
body {
position: relative;
/* 임의로 준 position */
}
#modal_container {
display: none;
}
.modal {
position: absolute;
width: 500px;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: var(--color-gray);
border-radius: 20px;
margin: 0 30px;
padding: 30px;
}
.modal .closeBtn img {
width: 35px;
height: 35px;
position: absolute;
top: 30px;
right: 30px;
cursor: pointer;
}
#member_image {
width: 150px;
height: 150px;
margin-bottom: 35px;
overflow: hidden;
border-radius: 100%;
}
#member_image img {
width: 100%;
height: 100%;
}
#member_name {
padding-bottom: 10px;
}
#member_info {
margin: 50px auto 0px;
}
#member_info .info_inner {
width: 400px;
margin-bottom: 20px;
padding: 15px;
display: flex;
align-items: center;
background: var(--color-white);
box-shadow: rgba(17, 17, 26, 0.1) 0px 0px 16px;
border-radius: 20px;
}
css는 머.. 간단하게 뼈대만 잡아두었고 최종적으로 다 합친 후에 전체 컨셉에 맞게 수정할 예정이다.
const closeBtn = document.querySelector('.closeBtn');
const modal = document.getElementById('modal_container');
const memberContents = document.querySelectorAll('.member_content');
const members = [
{
name: '신희범',
mbti: 'ISFP',
age: 23,
advantages: '끈기 있다.',
style: '꼼꼼하다.',
tmi: '더위를 많이 타서 여름이 힘들다...',
imgSrc: 'images/shin.jpg'
},
{
name: '김하영',
mbti: 'ISFJ',
age: 26,
advantages: '해야하는 일에 대해 계획성 있게 처리 가능해요',
style: '겁이 많지만 악바리로 해내는 스타일',
tmi: '빨래를 했는데 비가 옵니다...',
imgSrc: 'images/kim.jpeg'
},
{
name: '송재헌',
mbti: 'ISTJ',
age: 28,
advantages: '궁금증이 정말 많아서 이것저것 도전해본다.',
style: '비전공자라 굉장히 꼼꼼하게 찾아보지만 결국엔 GPT 의 도움을 받는다.',
tmi: '24시간 에어컨 틀고 있어서 전기세가 걱정됩니다. 그리고 지금 음악 듣고 싶네요.',
imgSrc: 'images/song.jpg'
},
{
name: '서영진',
mbti: 'ESFJ',
age: 30,
advantages: '가끔씩 나서길 좋아한다..! 그래서 분위기를 좋게 만든다.',
style: 'chat gpt와 대화를 잘 나눈다....?ㅎㅎ',
tmi: '맛있는 거 먹으면서 살 찔 때가 제일 좋아...',
imgSrc: 'images/seo.jpg'
},
{
name: '이지영',
mbti: 'ISFJ',
age: 30,
advantages: '마음먹은건 어떻게 해서든 꼭 해내요!',
style: '계획적이고 체계적인걸 좋아하는 스타일',
tmi: '강아지가 편식을 해요... 배가 불렀나봐요..',
imgSrc: 'images/lee.jpg'
},
]
여기서 memberContents
변수는 완성화면에서 보였던 사람1~사람5까지의 버튼으로
다른 팀원분들과 합친 코드에서는 이 부분이 팀원 사진이 될 예정이다.
closeBtn.addEventListener('click', () => {
modal.style.display = "none";
})
위에서 만든 닫기버튼 변수 closeBtn
에 클릭이벤트를 추가해서 modal
이 display:none
되도록 만들었다.
memberContents.forEach((memberContent, idx) => {
memberContent.addEventListener('click', () => {
modal.style.display = "block";
// 멤버 사진
const imgBox = document.getElementById('member_image');
imgBox.innerHTML =
`
<div id="member_image">
<img src="${members[idx].imgSrc}">
</div>
`
})
})
사진,이름,나이,기타 내용 모두 forEach
반복문으로 순회하면서 생성되게끔 구현하려고 했다.
1. 그래서 우선 member_contents
전체 내용을 하나씩 순회시키고 매개변수로 memberContent
, 순서를 알기 위해 idx
를 지정했다.
2. memberContent
를 클릭하면 모달이 등장한다.
3. imgBox
를 html에 있던 div태그를 가져오고 이 안에 innerHTML
으로 이미지를 넣어주었다.
members[idx].imgSrc
에 맞게 이미지가 불러와지는데, 예를들어 [idx]
가 0이면 첫번째 사람의 사진이 데이터로 가져와서 태그에 넣어진다.
memberContents.forEach((memberContent, idx) => {
memberContent.addEventListener('click', () => {
modal.style.display = "block";
// 멤버 사진
const imgBox = document.getElementById('member_image');
imgBox.innerHTML =
`
<div id="member_image">
<img src="${members[idx].imgSrc}">
</div>
`
const memberName = document.getElementById('member_name');
const memberAge = document.getElementById('member_age');
memberName.innerText = members[idx].name;
memberAge.innerText = members[idx].age + "살";
})
})
이름과 나이도 동일한 방식으로 넣었다. 텍스트만 불러와서 해당 태그에 들어가면 되므로 백틱을 사용하여 넣을 필요는 없었다.
memberContents.forEach((memberContent, idx) => {
memberContent.addEventListener('click', () => {
modal.style.display = "block";
//짧게 보기 위해 윗부분 생략
//멤버 내용
const memberInfo = document.getElementById('member_info');
memberInfo.innerHTML =
`
<div class="info_inner">
<img src="images/icon-agree.png" alt="협업" class="icon">
${members[idx].style}
</div>
<div class="info_inner">
<img src="images/icon-positive.png" alt="장점" class="icon">
${members[idx].advantages}
</div>
<div class="info_inner">
<img src="images/icon-tmi.png" alt="tmi" class="icon">
${members[idx].tmi}
</div >
`
})
})
멤버 소개에 대한 내용도 이미지 넣는 방식과 똑같은 방식으로 간단히 구현했다.
javascript
memberContents.forEach((memberContent, idx) => {
memberContent.addEventListener('click', () => {
modal.style.display = "block";
// 멤버 사진
const imgBox = document.getElementById('member_image');
imgBox.innerHTML =
`
<div id="member_image">
<img src="${members[idx].imgSrc}">
</div>
`
//멤버 이름, 나이
const memberName = document.getElementById('member_name');
const memberAge = document.getElementById('member_age');
memberName.innerText = members[idx].name;
memberAge.innerText = members[idx].age + "살";
//멤버 내용
const memberInfo = document.getElementById('member_info');
memberInfo.innerHTML =
`
<div class="info_inner">
<img src="images/icon-agree.png" alt="협업" class="icon">
${members[idx].style}
</div>
<div class="info_inner">
<img src="images/icon-positive.png" alt="장점" class="icon">
${members[idx].advantages}
</div>
<div class="info_inner">
<img src="images/icon-tmi.png" alt="tmi" class="icon">
${members[idx].tmi}
</div >
`
})
})
간단한 코드였지만 이미지를 넣는 부분이 계속 안 돼서 살짝 애먹었었다..ㅎㅎ
member
배열에 담긴 imgSrc
의 경로를 먼저 확인//참고한 코드
const img = document.createElement('img');
img.src = members[index].imageSrc;
img.alt = members[index].name;
modalInfo.innerHTML = '';
modalInfo.appendChild(img);
개인프로젝트 했을 때 만들어 본 코드여서 똑같이 createElement
로 이미지 태그를 만들고 그 안에 이미지들을 넣고 appendChild
를 해주었다.
❌ 발생한 문제점 : 이미지가 사람을 클릭할 때마다 appendChild()
로 계속 추가되기만했다.
🔍 두 코드의 차이점 : 나는 이미 member_image
라는 태그를 만들어서 위치를 잡아두고 그 안에 이미지를 넣는 방식이었고,
위 코드는 아예 아무것도 없는 큰 div 박스 안에 이름 밑에 사진이 추가되게 만들기 위해 appendChild()
를 사용했던 것이다.
💡 해결책 : 나는 이미 이미지가 들어갈 공간을 만들었기 때문에 createElement
로 이미지 태그를 만들 필요도 없고 appendChild()
로 밑에 추가되라는 메소드를 사용할 필요가 없던 것!!
결과적으로 나는 1) html에 만든 이미지 태그를 변수로 저장하고, 2) 그 안에 member
변수에 있던 이미지소스를 각 순번에 맞게 불러와서 넣어주기만 하면 되는 간단한 문제였당..ㅎㅎ
퍼블리셔를 배우면서 모달창은 많이 만들어봤고 스크립트 공부하면서도 제이쿼리를 사용하지 않아도 만들 수 있게 되어서 복습 겸 빠르게 할 수 있을 줄 알고 모달 부분을 맡았는데 생각보다 오래걸려서 당황스러웠다.
여전히 forEach
문을 사용하는게 익숙하지 않다는 걸 느껴서 기본 예제 말고 실제로 사용되는 코드들을 보면서 연습해야할 것 같다.
또 비슷해보이는 코드일지라도 그 코드가 내가 만들고자 하는 코드와 정확히 맞는지, 변경할 코드는 없는지 비교한 후 적용해야겠다.
남은 과제