이미 서비스 중인 사이트를 clone하는 clone coding 프로젝트로
대상 사이트는 "https://www.osulloc.com/" 입니다.
clone coding
클론 프로젝트는 순수 개발시간의 극대화를 위해 기획이나 디자인 시간을 제외하기 위하여 진행하는 것으로 사이트의 구조나 소스만 참고하고 로직이나 구현방법은 직접 코딩하였습니다.
프론트엔드: ReactJs, Sass
백엔드: Django, MySQL
배포 : AWS
소스관리:git, github
프론트엔드 3명, 백엔드 2명으로 구성되었으며
본인은 프론트엔드 개발자로써 참여하여
login페이지, main페이지, comment기능,
상품리스트 페이지의 video slide을 담당하였습니다.
회원가입
class Signup extends Component {
constructor() {
super();
this.state = {
realname: "",
username: "",
birthday: "",
gender: "",
provider: "",
phone: "",
password: "",
password_confirm: "",
};
}
// 페이지 이동 함수 //
goToMain() {
const token = localStorage.getItem("token");
fetch(`${url}/user/sign-in`, {
method: "POST",
headers: {
Authorization: token,
"Content-Type": "application/json",
},
body: JSON.stringify({
username: this.state.id,
password: this.state.password,
}),
}).then((response) => {
if (response.status === 401) {
alert("아이디 혹은 비밀번호가 일치하지 않습니다.");
}
if (response.status === 400) {
alert("서버에 일시적으로 오류가 발생하였습니다.");
}
if (response.status === 200) {
response.json().then((res) => localStorage.setItem("token", res.token));
this.props.history.push("/");
}
});
}
componentDidMount() {
// Step1. scroll 이벤트 add //
// javascript 윈도우 객체의 scroll 이벤트 가져와서 준비 //
window.addEventListener("scroll", this.addScrollFunc.bind(this)); //"scroll"이 내장이벤트 default이름임
// Step End. 자동 스크롤 이벤트 계속 요청할 함수 //
// 2초 딜레이 후 시작 //
setTimeout(() => {
this.timer = setInterval(
this.scrollAutoMovingFunc.bind(this),
this.intervalNum
);
}, 1500);
}
원래 사이트에서는 브랜드를 소개하는 페이지로, 스크롤이벤트에 따라 이미지와 텍스트들을 보여주고 있는 페이지이다.
해당 페이지를 구현할때는 리액트에서 직접적으로 scroll이벤트를 할 수가 없어 직접 BOM(Browser Object Model)의 window객체에 접근하였다.
윈도우 객체에 접근하여 javascript의 이벤트를 메서드인addEventListener
이용하여 scroll
이벤트를 사용케 하였다.
그리고 특정스크롤 값에서 요소들이 transform(translate)되는 interactive한 이벤트를 구현하였다. 또한 타이머함수(setInterval)을 사용하여 유저가 페이지로 진입시 초기에 자동으로 이벤트가 실행토록 하였다.
// map을 이용하여 화면에 데이터 구현 //
const test = arr.map((el) => {
if (el === this.state.pick) {
return (
<button className="pick" id={el}>
{el + 1}
</button>
);
}
// sort시 쿼리스트링을 이용하여 필요한 데이터 요청 //
componentDidUpdate = (prevProps) => {
if (this.props.location.search !== prevProps.location.search) {
fetch(`${url}/item/teashop/list${this.props.location.search}`)
.then((res) => res.json())
.then((res) => {
this.setState({ data: res.items, num_pages: res.num_pages });
});
}
};
상세 페이지 상단
componentDidMount = () => {
fetch(
`${urlset}/item/teashop/detail/${this.props.match.params.minchang}`,
{}
)
.then((response) => response.json())
.then((response) => {
this.setState({
benefits: response.item.benefits,
best: response.item.best,
bonus: response.item.bonus,
gift: response.item.gift,
neww: response.item.new,
on_sale: response.item.on_sale,
sold_out: response.item.sold_out,
sub_category: response.item.sub_category,
fourth_category: response.item.fourth_category,
description: response.item.description,
main_image: response.item.main_image,
price: Math.floor(response.item.price),
num_reviews: response.item.num_reviews,
rating: response.item.rating.overall_rating__avg,
title: response.item.title,
item: response.item,
discount_percent: response.item.discount_percent,
});
this.bottomTagCheck();
this.revNum();
});
};
상세 페이지 댓글 output
render() {
const TapObj = {
1: <Tap1 />,
2: (
<Tap2
commentList={this.state.commentList}
getFunc={this.getFunc.bind(this)}
id={this.props.match.params.id}
/>
),
3: <Tap3 />,
};
const { tapInx, commentList } = this.state;
return (
// CommentOutput.js
class CommentOutput extends Component {
render() {
return (
<div className="commentOutput">
{this.props.commentList.map((item, index) => {
return (
<CommentOutputChild
key={index}
commentUser={item.username}
commentDate={item.date}
commentScore={item.overallrate}
commentText={item.comment}
/>
);
})}
</div>
상세 페이지 댓글 input
//commentStar.js
const starColor = {
width: `${this.props.score * 20}%`,
};
//comment.js
<CommentStar
score={this.state.score}
scoreHandler={(input) => this.setState({ score: input })}
Number
이지만 별 이미지를 클릭하는 기능을 통해 값을 입력받는 기능을 구현해보았다. getData = () => {
const token = localStorage.getItem("token");
console.log("getData 실행");
fetch(url + "/order/cart", {
method: "GET",
headers: {
Authorization: token,
},
})
.then((res) => res.json())
.then((res) =>
this.setState({
feeds_arr: res.items,
price_arr: res.summaries,
empty_feed: true,
})
);
};
리액트를 배우고 처음으로 실제사이트처럼 만드는 것이 프로젝트였습니다.
그렇기에 리액트의 기본기를 학습하고자 했습니다.
담당부분 코드에 대한 자세한 후기 : https://velog.io/@jongsunpark88/projectW1me
처음 리액트를 배울 때가 기억납니다.
과연 잘 할수 있을까? 어렵다고 하는데 제대로 쓸 수 있을까?
그러나 프로젝트를 진행하다보니.. 학습했던 리액트가 실제로 적용되는 것을 보면서 어느새 react를 즐기고 있는 제 자신이 보였습니다.
하나하나 생각한 것들이 만들어지고 새로운 것이 만들어지는 것을 보다보면
너무나도 즐거웠습니다.
역시 기본인 javascript 기본기는 더욱 필요하다는 것.
리액트는 도구이고 기본은 javascript. 그리고 더 나아가 브라우저 자체에 대한 이해.
하지만 이제 걱정은 없습니다.
무엇을 해야되는지 알았다는 것은 즐거운 것이니까요.ㅎ
위코드 선배님! 잘읽었습니다!