이번 1차 프로젝트는 지금까지 배운 프론트엔드와 백엔드 지식들을 바탕으로 선정된 사이트를 클론 코딩해보는 방식으로 진행되었다. 팀원은 나 자신을 포함하여 5명으로 구성되었고, 5명 모두 프론트엔드와 백엔드에서 업무를 분담하여 1주는 프론트엔드, 다른 1주는 백엔드를 개발하는 방식으로 프로젝트가 진행되었다. 팀명은 클론 코딩할 사이트의 이름에서 따와서 thisisnevercode 로 정했다.
thisisneverthat 사이트
thisisnevercode 프론트엔드 GitHub
thisisnevercode 백엔드 GitHub
thisisnevercode 배포
메인 페이지(김태규)
리스트 페이지(김민재)
Nav & Footer(김휘민)
상세 페이지(김동권)
회원가입 & 로그인(윤창현)
상세 페이지 API (김태규)
리스트 페이지 API (김동권)
정렬 API (김휘민)
카테코리 API (윤창현)
회원가입 및 로그인 API (김민재)
지금까지 동기 분들과 함께 공부하면서도 항상 팀이 존재했고, 함께 미션을 수행하면서 의견을 나누고 서로의 코드도 리뷰해주면서 진행해왔지만, 프로젝트를 5명의 협업으로 진행하는 것은 다른 차원의 문제였다.
일단 5명의 업무가 정확하게 분배되어 있기 때문에 본인이 맡은 부분을 잘 구현해야겠다는 책임감을 많이 느꼈고, 지속적으로 팀원들과 소통을 하기 위해서는 본인의 코드뿐 아니라 다른 팀원들의 코드와 프로젝트의 전체적인 흐름을 파악하는 것이 중요하다고 느꼈다. 같은 이유로 본인의 코드는 팀원들에게 읽히기 때문에 이해하기 쉽도록 작성해야 하고, 꾸준하게 리팩토링하는 것이 중요하다고 생각했다.
각자의 결과물을 깃헙을 통해서 합치고, 프론트엔드와 백엔드의 결과물을 합칠 때에는 많은 시행착오를 겪었다. 하지만 그런 과정을 거치면서 개발자로서 성장하는 것을 느꼈고, 코딩 실력을 기르는 것도 물론 중요하지만 동료들에게 함께 일하고 싶은 개발자가 되야겠다고 다짐했다.
시간이 촉박한 편이었고, 5명 모두 프로젝트 경험이 처음이었기 때문에 처음에 프로젝트를 계획할 때, 너무 이것저것 욕심부리기보다는 기본적인 것에 충실하자고 의견을 모았다. 그래서 구현하지 못한 기능이 있는데, 조금 더 미리 계획을 잘 세웠다면 욕심내서 추가적으로 구현해볼 수 있는 부분이 있었을 것이라고 생각했다. 2차 프로젝트를 진행할 때는 1차 때를 교훈 삼아서 많은 부분을 구현해보고 싶다.
메인 페이지에 이미지 슬라이드를 반응형으로 구현했는데 브라우저 창의 크기가 클 때에는 기본적으로 슬라이드에 4개의 이미지가 보여지는데 버튼을 눌렀을 때 4개의 이미지 중에서 2개씩 넘어가게 구현을 했고, 창의 크기가 작을 때에는 컨텐츠가 재배치 되어서 슬라이드에 2개의 이미지가 보여지고 버튼을 눌렀을 때 1개씩 넘어가도록 구현했다.
반응형을 고려하여 창의 크기에 따라 경우를 나눴고 각 경우마다 수학적인 로직이 들어갔기 때문에 재미있게 코딩할 수 있었다.
class ImageSlide extends Component {
constructor() {
super();
this.state = {
imagePosition: 0,
};
}
changeImageToLeft = position => {
const slideLength = this.props.images.length;
let newPosition = position - 1;
let maxPosition;
if (window.innerWidth > 1140) {
maxPosition = Math.ceil((slideLength - 4) / 2); // 큰 화면용
} else {
maxPosition = Math.ceil(slideLength - 2); // 작은 화면용
}
if (newPosition < 0) newPosition = maxPosition; // 오른쪽 최대치 넘어가면 제일 왼쪽으로 되돌림
this.setState({
imagePosition: newPosition,
});
};
changeImageToRight = position => {
const slideLength = this.props.images.length;
let newPosition = position + 1;
let maxPosition;
if (window.innerWidth > 1140) {
maxPosition = Math.ceil((slideLength - 4) / 2); // 큰 화면용
} else {
maxPosition = Math.ceil(slideLength - 2); // 작은 화면용
}
if (maxPosition < newPosition) newPosition = 0; // 왼쪽 최대치 넘어가면 제일 오른쪽으로 되돌림
this.setState({
imagePosition: newPosition,
});
};
render() {
const { images } = this.props;
const { imagePosition } = this.state;
return (
<div className='ImageSlide'>
<div className='slideBox'>
<button
className='slideBtn btnPrev'
onClick={() => this.changeImageToLeft(imagePosition)}
>
<FontAwesomeIcon icon={faChevronLeft} size='2x' />
</button>
<button
className='slideBtn btnNext'
onClick={() => this.changeImageToRight(imagePosition)}
>
<FontAwesomeIcon icon={faChevronRight} size='2x' />
</button>
<div
className='slideList'
style={{
transform: `translateX(
${imagePosition * -50}vw`,
}}
>
{images &&
images.map(image => (
<Link
className='slideContent'
to='/products/shoes'
key={image.id}
>
<img
className='slideImage'
alt={image.name}
src={image.imgUrl}
/>
</Link>
))}
</div>
</div>
</div>
);
}
}
export default ImageSlide;
프론트엔드 상세페이지에서 원하는 형태로 데이터를 가공하여 보내는 것을 목표로 코드를 짰다. 우선 데이터의 id 값에 해당하는 데이터를 1개씩 뽑아야했고, 객체 데이터 안에 value 값으로 detailImages 와 subImages 가 배열형태로 들어와야 했기 때문에 쿼리문으로 원하는 데이터를 뽑은 후, 마지막에 자바스크립트 문법으로 데이터 형태를 완성하였다.
// productDao.js
const getProductById = async (id) => {
const detailImages = await prisma.$queryRaw`
SELECT
key_number as keyNumber,
di.detail_image_url as detailImg
FROM
products P
LEFT JOIN
detail_images di
ON
di.product_id = p.id
WHERE
p.id = ${id}
`;
const subImages = await prisma.$queryRaw`
SELECT
key_number as keyNumber,
si.sub_image_url as subImg
FROM
products P
LEFT JOIN
sub_images si
ON
si.product_id = p.id
WHERE
p.id = ${id}
`;
const [product] = await prisma.$queryRaw`
SELECT
p.id,
p.name,
p.price,
p.description,
p.textile_information as textileInfo,
p.main_image_url as mainImg
FROM
products p
WHERE
p.id = ${id}
`;
if (product) {
product.detailImg = detailImages;
product.subImg = subImages;
}
return product;
};
태규님의 코드처럼 읽기 쉬운 글,, 잘봤습니다 고생많으셨습니다 디네코..😀 다음주에 디네댓 후드티 입고 오겠습니다,,