본문 바로가기
포스코x코딩온

[포스코x코딩온] 풀스택 부트캠프 14주차 정리 -1 3차 프로젝트 회고

by 김선지 2024. 1. 22.

01/18

로그인, 회원가입 페이지 백엔드, 프론트엔드 작업을 시작했다.

다만 회원가입 페이지에 들어가는 정보가 많아서 여러개의 form의 여러 컴포넌트를 만든 다음 props나 redux를 이용해서 state를 줄까 생각중이었다. 이런 생각을 가지고 리더님께 질문을 했는데, 그냥 하나의 form으로 모든 데이터를 넣고 next를 누르면 이전 페이지를 display none으로 설정하고 다음 페이지를 display block으로 설정하는 것이 훨씬 경제적일 거라고 말했다. 저번 프로젝트에서는 바로 생각해냈을 것 같은데 뭔가 리액트라서 다르다고 생각했던 게 아닌가 싶었다.

마이페이지도 따로 구현해야 하기 때문에 routes와 controller만 만들어놨다.

 

01/19

얼추 로그인과 회원가입 백엔드는 전부 구축을 완료했다. 그래서 mypage 백엔드 api를 만들었다. 이 페이지에 기능이 조금 많아서 처음에 render할 때 axios 요청을 많이 해야해서 코드가 조금 길다. 뭔가 효율적으로 할 방법이 있을까 싶긴 한데 내가 생각할 수 있는 선에서는 불가능하다. 진짜 많이 가져오는 건데 방법이 없다.

또한 바꿀 수 있는 비밀번호, learning language같은 정보를 수정할 수 있는 patch요청과 회원탈퇴 delete 요청같은 것도 추가했다.

+ 프로필 사진 기능도 추가한다는데 db에 새로 하나 추가해야겠다.

 

01/20 ~ 01/21

로그인, 회원가입 프론트엔드 만들기를 시작했다.

물론 form같은 경우는 backend를 구축하면서 미리 만들어놨기 때문에 비교적 수월했다. 다만 관건은 디자인인데....

다행히도 팀원분이 피그마에 디자인을 올려주셔서 해당 디자인을 참고해서 만들 수 있었다.

새로운 디자인을 뽑는 게 힘들 뿐이지 그냥 있는 디자인을 카피하는 건 쉬우니까 큰 문제는 없을 거라고 생각했다.

다만... 내가 처음에 만들었던 form 구조와 피그마에 있는 구조가 조금 달랐다.

gender를 고르는 것은 나는 select로 만들었는데 피그마에는 radio button으로 되어있었고

learning language같은 경우도 처음에는 하나만 나와있는데 플러스 버튼을 누르면 세개까지 추가되게 하는 게 좋다는 의견이 있었다. 그래서 이것도 어찌어찌 구현하고 select 디자인 수정도 완료했다. 하지만 모바일에서 자꾸 새로고침을 할 때마다 전체 form 크기가 작아지는 오류가 발생했다.

여러 시행착오 결과 태그를 이동하는 (ex) translateX) 속성을 현재 html 태그의 width 크기 이상으로 줘버리면 이런 오류가 발생하는 것 같았다. 그렇게 그 날의 bug fix를 완료했다.

대충 이렇게 만들었다.

 

01/22

갑자기 로그인 페이지의 디자인이 조금 다르게 되어있었다. 알고보니까  route 컴포넌트로 import 하는 파일들이 필터링이 되었다고 생각했는데도 이건 내 착각이었고  모든 scss가 적용된다는 사실을 알게 되었다. 그래서 내가 input, button 이런 식으로 설정해놨던 태그들 또한 다른 분들 컴포넌트에 가있었고 나 또한 다른 컴포넌트에서 온 scss가 적용되었다. 그래서 전체 컴포넌트를 감싸는 태그에 클래스 이름을 따로 주고 이 클래스 안에서 scss를 설정하는 것으로 오류를 해결할 수 있었다. 그리고 다른 분들의 css 침범은 따로 선택자 특이성을 조금 더 강하게 줌으로써 해결할 수 있었다.

또한 백엔드 서버의 에러처리 핸들러를 구현했고

로그인 정보가 없을 때는 '/' 에 해당하는 메인 페이지를 login페이지로 설정했고 로그인 정보가 있을 때는 post 페이지로 이동하게 만들었다. 그냥 삼항 연산자로 하면 되는 거였기에 크게 힘들거나 하지는 않았다.

다른 분들이 막히거나 오류가 생기면 날 부른다.. 뭐 이전 프로젝트에도 있었던 일이긴 하고 나도 이걸 설명하면서 같이 성장할 수 있지만 그거때문에 작업할 시간이 적어지는 것도 팩트다.. 이 사이에서의 균형을 잡고 싶다.

이제 post 페이지를 담당하게 될 것 같은데... 뭐 이게 힘들다는 건 아닌데 왜 이렇게 의욕이 안생기는지 모르겠다.

 

01/23

팀원분이 데이터 테이블을 정의해두긴 하셨는데 primary key와 좋아요 부분에서 조금 수정할 게 있었다.

좋아요 같은 경우에는 일반적으로 인스타나 페이스북처럼 유저 정보를 넣어주고 만약에 내가 좋아요를 한 상황이라면 다시 한번 눌렀을때 토글형식으로 데이터를 없애야 하기 때문에 mySQL의 경우에는 하나의 컬럼으로 넣어버리면 아마도 구현할 방법이 없을 것 같다.

그래서 post테이블과 User 테이블, 이 두개의 테이블과 1:N 관계를 맺는 PostLikes라는 테이블을 만들어서 좋아요를 관리하면 될 것 같았다.

(테이블 안에는 모든 포스트에 해당하는 좋아요가 있다. 만약에 내가 한 좋아요에 해당하는 post를 불러온다면 PostId를 엮어서 가져오면 될 것 같다.) 뭐 간단한거니까 바로 구현이 되긴 했는데 sequelize에서 [Post 정보: object 와 user name: string, 좋아요 수: number, 내가 좋아요 했는지 여부: boolean], 이걸 하나의 배열로 가져오고 싶었는데 이건 실패했다. (프론트 단에서 불러온 데이터를 토대로 map을 돌리셔야 하니까)

다른 table의 column같은 경우에는 그냥 include 속성을 활용하면 되는데 count 집계함수를 이용한 변수도 포함 하기에는 구글링을 해도 잘 나오지 않았다. 물론 가능하긴 하겠지만... 내 실력 부족이다. 나중에 제대로 알아보자.

그래서 post 정보, 좋아요 수, 좋아요 여부를 따로 만들어서 새로운 배열에다가 집어넣었다. 뭐 해결은 되었으니까 된건가 싶기는 한데 아무래도 배열이 많다는 건 그만큼 시간이 오래 걸린다는 거라서 조금 찝찝하긴 하다.

 

PostLikes

 

이런 식으로 짜봤다. 동작은 되는데 살짝 아쉬움이 남긴 한다.

export const getPosts = async (
    req: Request,
    res: Response,
    next: NextFunction
) => {
    let allPosts: Array<postsInterface> = [];

    let { userid: myUserid } = req.body;
    if (!myUserid) {
        myUserid = '';
    }
    try {
        allPosts = await Post.findAll({
            attributes: ['postId', 'userid', 'content', 'createdAt'],
            include: [
                {
                    model: User,
                    attributes: ['name'],
                },
            ],
        });
    } catch (err) {
        return next(err);
    }
    if (!allPosts || allPosts.length < 1) {
        return res.json({ msg: `Maybe there's no post here!`, isError: true });
    }
    let PostsDatas = [];
    for (let i = 0; i < allPosts.length; i++) {
        try {
            const likeCount = await PostLikes.count({
                where: {
                    PostId: allPosts[i].postId,
                },
            });

            const myLikeData = await PostLikes.findOne({
                where: {
                    PostId: allPosts[i].postId,
                    userid: myUserid,
                },
            });

            if (myLikeData) {
                PostsDatas.push([allPosts[i], likeCount, true]);
            } else {
                PostsDatas.push([allPosts[i], likeCount, false]);
            }
        } catch (err) {
            return next(err);
        }
    }
    // map으로 render 가능하게 PostDatas[0][0] = allPosts, PostDatas[0][1] = likeCount, PostDatas[0][2] = myLikeData(boolean)
    res.json({
        PostsDatas: PostsDatas,
        idError: false,
    });
};

 

음.. 그리고 댓글은 내가 할거라고 생각 안했는데... 댓글도 내가 하게 되었다. 이렇게 된 이상 댓글도 기능 제대로 넣어줘야겠다. 

댓글 기능을 만들게 된다면 comment 테이블을 하나 만들고 거기다가 get, post, patch, delete 기능을 쓰는 controller를 만들고 column은 number(primary key, autoIncrease), index(foreign key, index of Post), userid(foreign key of user) content로 해두고

 

댓글 좋아요 테이블을 따로 만들어서 comment의 index(primary key, autoIncrement)컬럼을 외래키로 하는 속성을 가지게 하고 number(primary key, autoIncrease), index(foreign key, index of Comment), userid(foreign key of user)로 해둬야겠다.

 집에서 하는게 확실히 학원에서 하는 것보다 2배는 효율이 잘나오지만 그렇게 되면 학원에서 할 게 없으니까 학원에서 해야겠다. 일단 이렇게 생각만 해두자.

그리고 post가 culture와 language 두개가 있어야 한다고 했으니까. 댓글 작업을 마치고 나면

post 생성, 좋아요 기능과 댓글 생성, 좋아요 기능의 똑같은 작업을 하나 더 해주고 앞에 culture를 붙여야겠다.

뭔가 내 손이 닿지 않는 부분이 없는 것 같은 건 기분탓이겠지 빨리 유데미 서버나 복구됐으면 좋겠다. 강의좀 듣게