오늘의 목표

더보기

✔️ 개인 과제 구현 


⏱️ 오늘의 일정

10:00 ~ 11:00 - 스탠다드반 CS 강의

11:00 ~ 19:00 - 개인과제 구현

19:00 ~ 20:30 - 챌린지반 수업


📜 스탠다드 반 CS 강의

10:00 ~ 11:00 - 스탠다드 반 CS 강의

 

매주 화목에 진행하는 스탠다드반 수업 강의가 있어서 참여했다.

오늘 내용은 이더넷, 허브, 스위치, Mac 주소에 관해 배웠다.

 

📜 개인과제 구현

11:00 ~ 19:00 개인과제 구현

 

git Commit 목록

 

오늘은 속도가 좀 붙어서 로그인 기능과 캐릭터 생성, 캐릭터 삭제, 캐릭터 조회, 아이템 생성 까지 구현했다.

 

로그인 기능에서 고민이 있던 부분을 포스팅하고자 한다.

처음에는 로그인 할때 아이디와 비밀번호가 맞으면 AccessToken을 생성해 반환해주는 걸로 우선 구현을 했다.

 

이렇게 구현하다가는 만약 재로그인한 대상이 해당 유저가 아닐 경우에는? 어떻게 해야할까? 라고 생각이 들어서 재로그인할때는 AccessToken을 살펴보기로 하고 구현했다.

 

내가 생각한 로그인 방식은 다음과 같다.

 1. 로그인 요청한 대상이 AccessToken을 가지고 오지 않았으면

  1.1 처음 발급 하는것이므로 AccessToken과 RefreshToken을 발급하고 로그인 성공 처리한다.

 2. 로그인 요청한 대상이 AccessToken을 가지고 오면

  2.1 해당 AccessToken이 유효한지 판단한다.

   2.1.1 AccessToken이 유효하면 로그인 성공 처리한다.

   2.1.2 AccessToken이 유효하지 않으면, RefreshToken을 가지고 있는지 확인한다.

    2.1.2.1 RefreshToken을 가지고 있으면, RefreshToken이 유효한지 판단한다.

     2.1.2.1.1 RefreshToken이 유효하면, AccessToken을 재발급하고 로그인 성공 처리한다.

     2.1.2.1.2 RefreshToken이 유효하지 않으면, RefreshToken과 AccessToken을 재발급하고 로그인 성공 처리한다.

    2.1.2.2 RefreshToken을 가지고 있지않으면, RefreshToken을 발급하고 AccessToken을 재발급하고 로그인 성공처리

 

위처럼 생각하고 구현해보니 어떻게해도 무조건 로그인은 성공처리가 되는것이 아닌가?

 

다시한번 생각하니 로그인 처리에서는 AccessToken과 RefreshToken을 발급 하는것이 목적인것이고 ( 아이디와 비밀번호만 맞으면 ), 클라이언트에서는 AccessToken을 가지고 로그인을 제외한 다른 작업을 할때, '검증' 하는 것을 목적으로 삼으면 되는것이니까.

 

로그인 처리에서는 앞서 언급했듯이 아이디와 비밀번호만 맞으면 로그인 성공처리로 해주면 되겠구나라는 생각이 들어서 그대로 진행했다.

 

로그인 처리를 제외하고는 다른 캐릭터 생성, 캐릭터 삭제 등 인증이 필요한 곳에는 AccessToken으로 검증을 해 해당 값이 유효하지 않으면 바로 에러를 반환하도록 구현했다.

 

위처럼 생각한 것이 맞는지는 확신할 수 없다.

 

https://velog.io/@chuu1019/Access-Token%EA%B3%BC-Refresh-Token%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EA%B3%A0-%EC%99%9C-%ED%95%84%EC%9A%94%ED%95%A0%EA%B9%8C

 

🧐 Access Token과 Refresh Token이란 무엇이고 왜 필요할까?

JWT 토큰은 유저의 신원이나 권한을 결정하는 정보를 담고 있는 데이터 조각이다. JWT 토큰은 비밀키로 암호화되어 있기에 비교적 안전하다. 그런데 탈취 당했을 때가 문제다!! 어떻게 위험을 최

velog.io

위 글을 보면 맞는거 같기도 하고.. 애매..

 

내일 과제를 완료하면 따로 튜터님한테 가서 물어보긴 해야겠다.

 

로그인

// 로그인
router.post('/sign-in', async (req, res, next) => {
    const { id, password } = req.body;
    const user = await prisma.users.findFirst({
        where: { id }
    });

    // 아이디와 비밀번호 검사
    if (!user) {
        return res.status(401).json({ message: `${id}은 존재하지 않는 아이디 입니다.` });
    }
    else if (!(await bcrypt.compare(password, user.password))) {
        return res.status(401).json({ message: `비밀번호가 일치하지 않습니다.` });
    }

    // 재로그인할때 필요한 accessToken을 가져옴
    const c2sAccessToken = req.cookies.accessToken;    

    let s2cAccessToken = 0;
    let s2cRefreshToken = 0;

    // accessToken 발급 여부 판단
    let newAccessToken = false;

    if (!c2sAccessToken) // 액세스 토큰이 없음
    {
        // 액세스 토큰 새 발행
        newAccessToken = true;
    }
    else // 액세스 토큰이 있음
    {        
        // 액세스 토큰 유효한지 확인
        // 유효하면 로그인 성공
        const [tokenType, token] = c2sAccessToken.split(' ');

        // tokenType이 맞는지 확인
        if (tokenType !== process.env.TOKEN_TYPE_CHECK) {
            return res.status(404).send('not found');
        }

        // 다른 유저의 AccessToken을 가지고 왔을 경우
        // 현재 로그인한 유저를 대상으로 AccessToken 재발행
        const myToken = CreateAccessToken(id);
        if (myToken !== c2sAccessToken)
        {
            newAccessToken = true;
        }
        else
        {
            // 나의 AccessToken을 가지고 오면 유효한지 확인
            const payload = ValidateToken(token, process.env.ACCESS_TOKEN_SECRET_KEY);
            if (!payload) // 액세스 토큰이 유효하지 않음
            {
                // 액세스 토큰 새 발행
                newAccessToken = true;
            }
        }        
    }

    // 액세스 토큰 새로 발급
    if (newAccessToken) {
        // DB에서 리프레시 토큰을 읽어옴
        const dbRefreshToken = await prisma.refreshTokens.findFirst({
            where: { userId: id },
            select: {
                token: true
            }
        });        

        // DB에 리프레시 토큰이 없음
        if (dbRefreshToken == null)
        {
            // 액세스 토큰과 리프레시 토큰을 새로 발급
            s2cAccessToken = CreateAccessToken(id);
            s2cRefreshToken = CreateRefreshToken(id);

            // 리프레시 토큰을 DB에 저장
            const newDBRefreshToken = await prisma.refreshTokens.create({
                data: {
                    userId: id,
                    token: s2cRefreshToken
                }
            });   

            // 쿠키 전달
            res.cookie('accessToken', s2cAccessToken);
            res.cookie('refreshToken', s2cRefreshToken);
        }
        else 
        {
            // DB에 리프레시 토큰이 있음

            const [tokenType, token] = dbRefreshToken.token.split(' ');

            // tokenType이 맞는지 확인
            if (tokenType !== process.env.TOKEN_TYPE_CHECK) {
                return res.status(404).send('not found');
            }

            // 리프레시 토큰이 유효한지 확인
            const dbRefreshTokenCheck = ValidateToken(token, process.env.REFRESH_TOKEN_SECRET_KEY);
            if (dbRefreshTokenCheck) // 리프레티 토큰이 유효함
            {
                // 액세스 토큰 발급
                s2cAccessToken = CreateAccessToken(id);                

                // 액세스 토큰 전달
                res.cookie('accessToken', s2cAccessToken);
            }
            else // 리프레티 토큰이 유효하지 않음
            {
                // 액세스 토큰과 리프레시 토큰을 새로 발급
                s2cAccessToken = CreateAccessToken(id);
                s2cRefreshToken = CreateRefreshToken(id);

                // 리프레시 토큰을 DB에 업데이트
                const newDBRefreshToken = await prisma.refreshTokens.update({
                    where: { userId: id },
                    data: {                        
                        token: s2cRefreshToken
                    }
                }); 

                // 쿠키 전달
                res.cookie('accessToken', s2cAccessToken);
                res.cookie('refreshToken', s2cRefreshToken);
            }
        }
    }

    return res
        .status(200)
        .json({ message: `${id}로 로그인 성공` });
});

 

 

캐릭터 생성, 캐릭터 삭제, 캐릭터 조회에서는 authMiddleware를 통해 검증하도록 구현했다.

export default async function (req, res, next) {
    const c2sAccessToken = req.cookies.accessToken;
    if (c2sAccessToken === undefined) {
        return res.status(404).json({ message: 'not found' });
    }

    const [tokenType, accessToken] = c2sAccessToken.split(' ');
    if (tokenType !== process.env.TOKEN_TYPE_CHECK) {
        return res.status(401).json({ message: '토큰 타입이 일치하지 않습니다.' });
    }

    // 토큰 검증
    const decodedToken = ValidateToken(accessToken, process.env.ACCESS_TOKEN_SECRET_KEY);
    if (!decodedToken) {
        return res.status(401).json({ message: '토큰이 만료되었습니다. 로그인을 다시 해주세요' })
    }

    const id = decodedToken.id;

    const user = await prisma.users.findFirst({
        where: {
            id : id
        }
    });

    if (!user) {
        return res.status(401).json({message:`${id} 사용자를 찾을수 없습니다.`})
    }

    req.user = user;

    next();    
}

 

로그인한 유저가 AccessToken을 들고오지 않았을 경우, TokenType이 일치하지 않을 경우,

그리고 Token이 만료할 경우 에러를 반환하도록했다.

오늘의 목표

더보기

✔️ 개인과제 발제

✔️ Node.js 강의

 


⏱️ 오늘의 일정

09:00 ~ 10:00 - 병원

10:00 ~ 11:00 - 개인과제 발제
11:00 ~ 11:30 - 팀 노션 작성

11:30 ~ 21:00 - Node.js 강의 듣기 


📜 병원

09:00 ~ 10:00 - 병원

 

엄마 수술 일정으로 인해 병원에 다녀왔다.

 

📜 개인과제 발제

10:00 ~ 11:00 - 개인과제 발제

 

줌으로 개인과제 발제가 있어서 참여했다.

이번에는 아이템 시뮬레이터를 할 수 있는 웹서버를 만드는 과제가 출제되었다.

아직 Node.js 강의를 다 수강하지 않아서 숙련까지 모두 토요일까지 듣고 과제를 시작할 수 있도록 해야겠다.

 

📜 팀 노션 작성

11:00 ~ 11:30 - 팀 노션 작성

 

3주차 새로운 팀에 배정되었다.

팀원분들과 얘기하고 노션에 간단한 정보를 입력했다.

다음주 월, 수에 개인과제를 팀원들끼리 공유해서 코드 리뷰 해보는 시간을 가지기로 했다.

 

📜 Node.js 강의 듣기 

11:30 ~ 21:00 - Node.js 강의 듣기 

 

2024.09.06 - [데이터베이스] - [DATABASE] Raw Query

 

[DATABASE] Raw Query

Raw Query는 SQL을 Node.js에서 사용해 데이터베이스에 쿼리를 요청 할 수 있는 방법이다.SQL을 알고 있으면 다양한 데이터베이스에 연결해 테이블을 생성하거나 데이터를 조회하는 등 다양하게 데이

program-yam.tistory.com

 

2024.09.06 - [데이터베이스/실습] - [DATABASE][실습] Raw Query 실습

 

[DATABASE][실습] Raw Query 실습

Node.js 에서 Raw Query를 사용하기 위해서 AWS RDS에서 대여받은 MySQL에 연결을 도와주는 데이터베이스 드라이버가 필요하다. 데이터베이스에 직접 SQL을 요청하고, 테이블을 생성하거나, 데이터를 삽

program-yam.tistory.com

 

2024.09.06 - [데이터베이스] - [DATABASE] ORM과 Prisma

 

[DATABASE] ORM과 Prisma

Prisma는 ORM ( Object Relational Mapping )으로써 Javascript 객체 ( Object )와 데이터베이스의 관계 ( Relation )을 연결 해주는 도구다. Prisma와 같은 ORM은 여러가지의 관계형 데이터베이스 ( RDB )를 사용할 수 있

program-yam.tistory.com

 

2024.09.06 - [데이터베이스/실습] - [DATABASE][실습] Prisma 시작하기

 

[DATABASE][실습] Prisma 시작하기

Prisma 라이브러리 설치# yarn 프로젝트를 초기화합니다.yarn init -y# express, prisma, @prisma/client 라이브러리를 설치합니다.yarn add express prisma @prisma/client# nodemon 라이브러리를 DevDependency로 설치합니다.yarn

program-yam.tistory.com

 

Raw Query와 ORM, Prisma에 대해 배웠다.

오늘의 목표

더보기

✔️ 프로그래머스 코테 문제 풀이

✔️ Node.js 강의 듣기

✔️ 챌린지반 OT 참여


⏱️ 오늘의 일정

9:00 ~ 10:00 - 프로그래머스 코테 문제 풀이

10:00 ~ 19:00 - Node.js 강의 듣기

19:00 ~ 20:00 - 챌린지반 OT 참여


📜 프로그래머스 코테 문제 풀이

9:00 ~ 10:00 - 프로그래머스 코테 문제 풀이

 

로또의 최고 순위와 최저 순위

https://github.com/YamSaeng/AlgorithmCodingTest/tree/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/1/77484.%E2%80%85%EB%A1%9C%EB%98%90%EC%9D%98%E2%80%85%EC%B5%9C%EA%B3%A0%E2%80%85%EC%88%9C%EC%9C%84%EC%99%80%E2%80%85%EC%B5%9C%EC%A0%80%E2%80%85%EC%88%9C%EC%9C%84

 

AlgorithmCodingTest/프로그래머스/1/77484. 로또의 최고 순위와 최저 순위 at main · YamSaeng/Algorithm

This is an auto push repository for Baekjoon Online Judge created with [BaekjoonHub](https://github.com/BaekjoonHub/BaekjoonHub). - YamSaeng/AlgorithmCodingTest

github.com

 

📜 Node.js 강의 듣기

10:00 ~ 19:00 - Node.js 강의 듣기

 

숙련 1주차 강의 듣기를 시작했다. 내일까지 숙련 1주차 수업듣기와 내용 정리를 완료하고

숙련 2주차 수업을 들을 수 있도록 해야겠다.

 

관계형 데이터 베이스 RDB에 대한 내용

2024.09.05 - [데이터베이스] - [DATABASE] 관계형 데이터베이스

 

[DATABASE] 관계형 데이터베이스

관계형 데이터베이스 ( RDB )는 각 데이터를 '테이블'이라는 표 형태의 구조에 저장한다.여기서, 각 '테이블'은 여러 정보를 저장하며, '테이블'간에 연관 관계를 설정해, 여러 테이블에 분산된 데

program-yam.tistory.com

 

AWS에서 RDS를 구매하고 사용하는 방법

2024.09.05 - [IT] - [AWS] RDS 구매하고 사용하기

 

[AWS] RDS 구매하고 사용하기

RDS는 AWS에서 제공하는 관계형 데이터베이스 서비스다.RDS는 서버 운영, 유지 보수, 백업과 같이 데이터베이스 관련 작업을 AWS에게 위임해서, 백엔드 개발자가 데이터베이스를 사용하는 것에 집

program-yam.tistory.com

 

SQL 문법

2024.09.05 - [데이터베이스] - [DATABASE] SQL ( Structured Query Language )

 

[DATABASE] SQL ( Structured Query Language )

SQL데이터베이스에서 사용하는 생성, 삽입, 조회 명령문을 SQL ( Structured Query Language )라고 한다. SQL의 종류DDL ( Data Definition Language )DML ( Data Manipulation Language )DCL ( Data Control Language )TCL ( Transaction Cont

program-yam.tistory.com

 

SQL 제약조건

2024.09.05 - [데이터베이스] - [DATABASE] SQL 제약조건

 

[DATABASE] SQL 제약조건

제약 조건 ( Constraint )은 각 컬럼들간의 제안사항을 관리하고,조건을 위반하는 데이터를 방지해 데이터베이스의 무결성 ( Integrity )을 보장하는 규칙이다. 무결성은 데이터가 결함없이 정확하고

program-yam.tistory.com

 

관계형 데이터베이스에 대한 개념, SQL 문법, SQL 제약 조건 등을 배웠다.

 

📜 챌린지반 OT 참여

19:00 ~ 20:00 - 챌린지반 OT 참여

 

챌린지반 OT에 참여했다.

게임서버에 관한 깊은 내용을 다룬다는 공지를 받았고, 그만큼 어려울 것이라는 말도 함께 들었다.

신청하면 평가를 받아서 참여 여부를 알려준다고 하는데 ㅠㅠ 

부디 참여해서 수업을 듣고 싶다.

 

오늘의 목표

더보기

✔️ 프로그래머스 코테 문제 풀이

✔️ CS 강의

✔️ Node.js 강의 듣기

✔️ Javascript 피드백 작성 


⏱️ 오늘의 일정

9:00 ~ 10:00 - 프로그래머스 코테 문제 풀이
10:00 ~ 11:00 - CS 강의

12:00 ~ 16:00 - Node.js 강의 듣기

16:00 ~ 17:00 - 베이직반 OT

17:00 ~ 21:00 - Node.js 강의 듣기


📜 프로그래머스 코테 문제 풀이

9:00 ~ 10:00 - 프로그래머스 코테 문제 풀이

 

기사 단원의 무기

https://github.com/YamSaeng/AlgorithmCodingTest/tree/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/1/136798.%E2%80%85%EA%B8%B0%EC%82%AC%EB%8B%A8%EC%9B%90%EC%9D%98%E2%80%85%EB%AC%B4%EA%B8%B0

 

AlgorithmCodingTest/프로그래머스/1/136798. 기사단원의 무기 at main · YamSaeng/AlgorithmCodingTest

This is an auto push repository for Baekjoon Online Judge created with [BaekjoonHub](https://github.com/BaekjoonHub/BaekjoonHub). - YamSaeng/AlgorithmCodingTest

github.com

 

풀이

function solution(number, limit, power) {
    let totalSum = 0;
    for (let i = 1; i <= number; i++) {

        let sum = 0;
        for (let j = 1; j <= i; j++) {
            if (i % j == 0) {
                sum++;
            }

            if (sum > limit) {
                sum = power;
                break;
            }
        }

        totalSum += sum;
    }

    return totalSum;
}

 

위처럼 코드를 구성해서 돌리니 시간초과가 났다..

수학공식이 필요한거 같아 구글을 뒤져보니 제곱근을 이용해 반복 수를 줄이는 방법을 찾았다.

 

function solution(number, limit, power) {
    let totalSum = 0;

    for (let i = 1; i <= number; i++)
    {
        let sum = 0;
        
        for (let j = 1; j <= Math.sqrt(i); j++)
        {
            if (i % j == 0)
            {
                if (i / j == j)
                {
                    sum += 1;
                }
                else
                {
                    sum += 2;
                }
            }

            if (sum > limit) {
                sum = power;
                break;
            }
        }

        totalSum += sum;
    }

    return totalSum;
}

 

코드로는 이해가 가는데, 원리적인 부분이 이해가 잘 안되서 

https://han-joon-hyeok.github.io/posts/programmers-knight-weapon/

 

프로그래머스 Level 1 - 기사단원의 무기 (JavaScript)

프로그래머스 - Level1 기사단원의 무기

han-joon-hyeok.github.io

 

여기 글을 참고해 이해했다.


📜 CS 강의

9:00 ~ 10:00 - CS 강의

 

컴퓨터 네트워크에 관한 수업

 

📜 베이직반 OT

16:00 ~ 17:00 - 베이직반 OT

 

2주차 수업인 Javascript에 관한 기초반에 대한 OT가 있어서 참여했다.

튜터님의 말로는 어느정도 캠프에서 제공한 Javascript 강의가 이해가 되고 진도가 나갔으면 굳이 듣지는 않아도 된다고 하셨다. 참여는 안하기로 했지만 영상과 강의 자료는 올라오면 볼 예정

 


📜 Node.js 강의 듣기

17:00 ~ 21:00 - Node.js 강의 듣기

 

MongoDB를 활용해 할일을 작성하고 DB에 저장해보는 웹 서버를 구현했다.

 

Node.js에서 사용하는 Middleware도 배웠다.

2024.09.03 - [Javascript] - [Javascript][Node.js] Middleware ( 미들웨어 )

 

[Javascript][Node.js] Middleware ( 미들웨어 )

미들웨어는 서버의 요청 ( Request ) - 응답 ( Response ) 과정에서 중간에 위치해 특정 기능을 수행하는 함수라고 볼 수 있다.예를 들어, 모든 요청에 대해 로그를 남기거나, 특정 사용자만 API를 접근

program-yam.tistory.com

 

오늘의 목표

더보기

✔️ 프로그래머스 코테 문제 풀기

✔️ Node.js 강의 듣기


⏱️ 오늘의 일정

9:00 ~ 10:00 - 프로그래머스 코테 문제 풀기
10:00 ~ 21:00 - Node.js 강의 듣기 


📜 프로그래머스 코테 문제 풀기

9:00 ~ 10:00 - 프로그래머스 코테 문제 풀기

 

덧칠하기

https://github.com/YamSaeng/AlgorithmCodingTest/tree/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/1/161989.%E2%80%85%EB%8D%A7%EC%B9%A0%ED%95%98%EA%B8%B0

 

AlgorithmCodingTest/프로그래머스/1/161989. 덧칠하기 at main · YamSaeng/AlgorithmCodingTest

This is an auto push repository for Baekjoon Online Judge created with [BaekjoonHub](https://github.com/BaekjoonHub/BaekjoonHub). - YamSaeng/AlgorithmCodingTest

github.com

 

📜 프로그래머스 코테 문제 풀기

10:00 ~ 21:00 - Node.js 강의 듣기 

 

대표적인 NoSql인 MongoDB를 배우고, MongoDB Cloud를 생성하는 방법, Studio 3T라는 Mongo DB 관리 툴, 코드로 Mongo DB에 접속하고 제어하는 방법을 배웠다.

 

2024.09.02 - [Javascript] - [Javascript][Node.js] Mongo DB

 

[Javascript][Node.js] Mongo DB

MongoDB는 모든 데이터가 JSON 형태로 저장된다.복잡한 데이터 구조를 쉽게 저장할 수 있는 장점이 있다. ( 대용량 데이터를 손쉽게 처리할 수 있다 )데이터베이스 서버의 확장을 손쉽게 줄이고 늘

program-yam.tistory.com

 

2024.09.03 - [분류 전체보기] - [Javascript][Node.js] Studio 3T

 

[Javascript][Node.js] Studio 3T

Studio 3T는 MongoDB를 위해 만들어진 MongoDB Client다 https://robomongo.org/ Robo 3T | Free, open-source MongoDB GUI (formerly Robomongo)Read by Dmitry Schetnikovichrobomongo.org 위 사이트를 통해 다운 받을 수 있다. MongoDB에 연

program-yam.tistory.com

 

2024.09.03 - [Javascript] - [Javascript][Node.js] MongDB 코드에서 연결

 

[Javascript][Node.js] MongDB 코드에서 연결

MongoDB 코드에서 연결mongoose를 이용해 데이터베이스에 연결할 수 있다. mongoosemongoose는 MongoDB에 데이터를 쉽게 읽고 쓰게 해주는 JavaScript 라이브러리다. Mongoose를 ODM ( Object Document Mapper ) 이라고 부

program-yam.tistory.com

 

 

오늘의 목표

더보기

✔️ 프로그래머스 코테 문제 풀이

✔️ 주특기 입문 / 숙련 발제

✔️ Node.js 강의 듣기


⏱️ 오늘의 일정

9:00 ~ 10:00 - 프로그래머스 코테 문제 풀이
10:00 ~ 11:00 - 주특기 입문 / 숙련 발제

13:00 ~ 21:00 - Node.js 강의 듣기


📜 프로그래머스 코테 문제 풀이

9:00 ~ 10:00 - 프로그래머스 코테 문제 풀이

 

소수 만들기

https://github.com/YamSaeng/AlgorithmCodingTest/tree/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/1/12977.%E2%80%85%EC%86%8C%EC%88%98%E2%80%85%EB%A7%8C%EB%93%A4%EA%B8%B0

 

AlgorithmCodingTest/프로그래머스/1/12977. 소수 만들기 at main · YamSaeng/AlgorithmCodingTest

This is an auto push repository for Baekjoon Online Judge created with [BaekjoonHub](https://github.com/BaekjoonHub/BaekjoonHub). - YamSaeng/AlgorithmCodingTest

github.com

 

📜 주특기 입문 / 숙련 발제

10:00 ~ 11:00 - 주특기 입문 / 숙련 발제

 

다음주 부터 본격적인 주특기 입문 / 숙련 강의 주차에 진입한다고 전달받았다.

화요일 부터는 베이직반, 목요일 부터는 챌린지 반이 시작된다.

베이직 반은 실습 중심 기초 수업으로 Node.js 에 대한 필수적인 내용을 주로 학습한다.

챌린지 반은 게임 서버 심화 이론 수업으로 게임 서버 개발에 관한 심도 있는 이론과 고급 기술을 학습한다.

 

두 반 모두 참여 할 수 있다고 공지받아서 두 수업 모두 참여할 생각이다.

 

📜 Node.js 강의 듣기

13:00 ~ 21:00 - Node.js 강의 듣기

 

기초 Node.js 강의 복습을 완료했다. 아직 정리 해야할것이 남아서 정리를 마치고, 주말에는 숙련 강의를 전부 듣고

정리할 예정.

 

2024.08.30 - [Javascript] - [Javascript] API Client ( Insomnia API Client )

 

[Javascript] API Client ( Insomnia API Client )

API Client란 개발단계에서 작성한 API의 요청을 확인하거나 테스팅 할 때 도움을 주는 툴이다.API Client를 사용함으로 개발 속도를 높이거나 잘못된 API 요청으로 인한 치명적인 에러를 예방하는데

program-yam.tistory.com

 

2024.08.30 - [Javascript] - [Javascript][Node.js] Request, Response

 

[Javascript][Node.js] Request, Response

RequestRequest란 클라이언트가 서버에게 전달하려는 정보나 메세지를 담은 객체를 의미한다.Request의 세부 사항에는 URL, http method, 헤더( header ), 쿼리 파라미터 ( query parameter ), 바이 데이터 ( body data

program-yam.tistory.com

 

2024.08.30 - [Javascript] - [Javascript][Node.js] Express.js - req, res 객체

 

[Javascript][Node.js] Express.js - req, res 객체

req 객체req.app : req 객체를 통해 Express.js의 app객체에 접근한다.req.ip : 요청한 클라이언트의 ip 주소가 담겨 있다.req.body : Request를 호출할 때 body로 전달된 정보가 담긴 객체다. ( express.json() 미들웨

program-yam.tistory.com

 

오늘의 목표

더보기

✔️ 알고리즘 세션 듣기

✔️ CS 세션 듣기

✔️ Node.js 강의 듣기

✔️ 알고리즘 유튜브 강의 듣기


⏱️ 오늘의 일정

9:00 ~ 11:00 - 알고리즘 세션 듣기
11:00 ~ 12:00 - CS 세션 듣기

12:00 ~ 13:00 - 점심

13:00 ~ 19:00 - Node.js 강의 듣기 

19:00 ~ 21:00 - 알고리즘 유튜브 강의 듣기


📜 알고리즘 세션 듣기

9:00 ~ 11:00 - 알고리즘 세션 듣기

 

알고리즘 세션이 있어서 수강했다. 오늘 내용은 스택과 큐에 관한 내용이였다.

중급자용 알고리즘 세션이 생긴다는 공지와 함께 , 입문용 알고리즘 세션이 모두 끝났다.

 

📜 CS 세션 듣기

11:00 ~ 12:00 - CS 세션 듣기

 

알고리즘 세션이 끝나자마자 CS 세션 수업이 있어서 바로 들었다.

발제자 2명의 발표를 듣고 튜터님의 강의를 들었다.

서버와 클라이언트에 관한 수업내용이였다.

 

📜 Node.js 강의 듣기 

13:00 ~ 19:00 - Node.js 강의 듣기 

 

캠프에서 제공한 Node.js 입문용 강의를 1주차까지 들었다.

Node.js, Express.js 에 대한 입문용 강의 였다.

수업내용은 정리해서 따로 포스팅 할 예정!

 

📜 알고리즘 유튜브 강의 듣기

19:00 ~ 21:00 - 알고리즘 유튜브 강의 듣기

 

알고리즘 유튜브 내용을 수강했다.

오늘은 배열에 관한 내용이였다.

오늘의 목표

더보기

✔️ 개인과제


⏱️ 오늘의 일정

9:00 ~ 21:00 개인과제


📜 개인과제

9:00 ~ 21:00 개인과제

 

11일에 이어서 개인과제를 진행했다.

game.js 에 몰려있던 클래스들을 각각 분리했다.

 

Logs.js  ( 로그 관리 )

let gInstance = null;

export class CLogs {    
    constructor() {
        if (gInstance) {
            return gInstance;
        }

        this._logs = [];
        gInstance = this;        
    }

    get logs() {
        return this._logs;
    }

    set logs(value) {
        this._logs.push(value);
    }

    printLogs() {
        this._logs.forEach((log) => console.log(log));
    }

    static getInstance() {
        return gInstance;
    }
}

 

Logs는 싱글톤 객체로 게임에 사용하는 모든 로그들을 관리한다.

 

 

Creature.cs ( 생명체 ( 플레이어와 몬스터 부모 ) )

class Creature {
    constructor() {
        this.bonusHP = 30;
        this.bonusRecovoryHP = 0.02;

        this.defenceState = DEFENCE_OFF;
        this.defenceRating = 0.4;

        this.attackPoint = 1;
        this.recovoryHP = 0.2;
        this.name = null;
        this.weapon = null;
        this.inventory = [];

        this.statusEffect = new CStatusEffect(this);
    }

    equipWeapon(weaponType) {
        switch (weaponType) {
            case '1':
                this.weapon = new CMaceWeapon(this);
                break;
            case '2':
                this.weapon = new CSwordWeapon(this);
                break;
            case '3':
                this.weapon = new CTwohandSwordWeapon(this);
                break;
        }
    }

    attack(battleTurn, target) {
        if (this.weapon != null) {
            return this.weapon.WeaponAttack(battleTurn, target);
        }
    }

    defence() {
        this.defenceState = DEFENCE_ON;
    }

    OnDamage(damagePoint) {
        if (this.hp - damagePoint < 0) {
            this.hp = 0;

            return true;
        }
        else {
            this.hp -= damagePoint;

            return false;
        }
    }

    StatusUpdate(stage) {
        this.hp += Math.floor(this.hp * this.recovoryHP) + (rand(1, 3) * stage);
        this.attackPoint += (rand(1, 3) * stage);

        this.recovoryHP += this.bonusRecovoryHP;        

        this.statusEffect.StatusInit();
    }

    Update(battleTurn) {
        let Logs = CLogs.getInstance();

        switch (this.statusEffect.Effect) {
            case STATUS_EFFECT_RESERVE_STUN:
            case STATUS_EFFECT_RESERVE_BLEEDING:
                this.statusEffect.Start(battleTurn);
                break;
            case STATUS_EFFECT_STUN:
            case STATUS_EFFECT_BLEEDING:
                this.statusEffect.Update(battleTurn);
                break;
        }
    }
}

 

Creature에는 StatusUpdate()로 Stage에 따라 랜덤하게 각종 능력치가 상승한다.

EquipWeapon()로 장비를 착용한다.

OnDamage()를 통해 데미지 처리를 한다.

Update()에서는 Creature에 출혈 및 기절 상태이상이 적용된다.

 

Player.cs ( 플레이어 )

export class Player extends Creature {
    constructor() {
        super();

        this.name = "플레이어";
        this.hp = 250;
        this.defensePoint = 0.5;
    }
}

 

플레이어는 선택한 무기로 바로 공격하기 때문에 부모의 attack()을 사용해 상대방을 공격한다.

 

Monster.cs ( 몬스터 )

export class Monster extends Creature {
    constructor() {
        super();

        this.name = "자바스크립트";
        this.hp = 100;
        this.defensePoint = 0.1;
        this.inventory.push(new CMaceWeapon(this));
        this.inventory.push(new CSwordWeapon(this));
        this.inventory.push(new CTwohandSwordWeapon(this));
    }

    attack(battleTurn, target) {
        let Logs = CLogs.getInstance();     

        let weaponChoiceNum = rand(0, 2);

        if (this.inventory.length > 0) {
            if (this.inventory[weaponChoiceNum] != null) {
                this.weapon = this.inventory[weaponChoiceNum];

                Logs.logs = chalk.yellow(`[${battleTurn}] ${this.name}가 ${this.weapon.name}을 장착했습니다.`);

                return this.weapon.WeaponAttack(battleTurn, target);
            }
        }
    }
}

 

몬스터는 attack()을 오버라이딩해서 자신이 소유하고 있는 무기 중 랜덤하게 골라 장착하고 상대방을 공격한다.

 

StausEffect.cs ( 상태이상 )

Update(battleTurn) {
        let Logs = CLogs.getInstance();

        this.EffectCount--;       

        switch (this.Effect) {
            case STATUS_EFFECT_STUN:
                Logs.logs = chalk.cyanBright(`[${battleTurn}] [${this.owner.name}] 기절!! [${this.EffectCount}] 턴 남음`);                
                break;
            case STATUS_EFFECT_BLEEDING:
                Logs.logs = chalk.cyanBright(`[${battleTurn}] [${this.owner.name}] 출혈!! 1턴당 [${this.damage}]씩 체력이 감소합니다. [${this.EffectCount}] 턴 남음`);
                this.owner.OnDamage(this.damage);                
                break;
        }              

        if (this.EffectCount == 0) {

            switch (this.Effect) {
                case STATUS_EFFECT_STUN:
                    Logs.logs = chalk.cyanBright(`[${battleTurn}] [${this.owner.name}] 기절 해제!`);
                    break;
                case STATUS_EFFECT_BLEEDING:
                    Logs.logs = chalk.cyanBright(`[${battleTurn}] [${this.owner.name}] 출혈 해제!`);
                    break;
            }

            this.StatusInit();
        }
    }

 

StatusEffect는 내부적으로 저장하고 있는 Effect의 값에 따라 상태이상을 owner에게 적용한다.

Start()로 상태이상을 적용하고, Update()를 통해 상태이상을 지속시킨다.

 

Weapon.js ( 무기 )

 WeaponAttack(battleTurn, target) {
     let Logs = CLogs.getInstance();

     if (this.owner.statusEffect.Effect == STATUS_EFFECT_STUN) {
         Logs.logs = chalk.cyanBright(`${this.owner.name}가 기절 상태이상에 걸려 공격할 수 없습니다.`);
         return false;
     }

     if (RatingSuccess(this.attackRating)) {
         if (target.defenceState == DEFENCE_ON) {
             target.defenceState = DEFENCE_OFF;

             if (RatingSuccess(target.defenceRating)) { // 상대방의 방어 확률에 따라 방어                                        
                 Logs.logs = chalk.yellow(`[${battleTurn}] ${target.name}가 ${this.owner.name}의 공격을 방어했습니다.`);

                 return false;
             }
             else {
                 Logs.logs = chalk.yellow(`[${battleTurn}] ${target.name}가 ${this.owner.name}의 공격을 방어하지 못했습니다.`);
             }
         }

         let damagePoint = rand(this.minAttackPoint + this.owner.attackPoint, this.maxAttackPoint + this.owner.attackPoint);
         let finalDamagePoint = Math.floor(damagePoint - damagePoint * target.defensePoint);

         if (target.statusEffect.Effect == STATUS_EFFECT_NONE) {
             if (RatingSuccess(this.statusEffectRating)) {
                 if (target.statusEffect != null) {
                     // 상태이상 적용
                     switch (this.weaponType) {
                         case WEAPON_MACE:
                             Logs.logs = chalk.magenta(`[${battleTurn}] ${target.name}에게 기절 상태이상 적용.`);

                             target.statusEffect.Effect = STATUS_EFFECT_RESERVE_STUN;
                             break;
                         case WEAPON_SWORD:
                             target.OnDamage(finalDamagePoint)

                             Logs.logs = chalk.magenta(`[${battleTurn}] ${target.name}에게 연속 공격!!`);
                             Logs.logs = chalk.green(`[${battleTurn}] ${this.owner.name} 공격 성공! ${this.owner.name}가 ${target.name}에게 ${finalDamagePoint} 의 피해를 입혔습니다.`);                                
                             break;
                         case WEAPON_TWO_HAND_SWORD:
                             Logs.logs = chalk.magenta(`[${battleTurn}] ${target.name}에게 출혈 상태이상 적용.`);

                             target.statusEffect.Effect = STATUS_EFFECT_RESERVE_BLEEDING;
                             target.statusEffect.damage = this.owner.attackPoint;
                             break;
                     }
                 }
             }
         }

         Logs.logs = chalk.green(`[${battleTurn}] ${this.owner.name} 공격 성공! ${this.owner.name}가 ${target.name}에게 ${finalDamagePoint} 의 피해를 입혔습니다.`);

         return target.OnDamage(finalDamagePoint);
     }
     else {
         Logs.logs = chalk.red(`[${battleTurn}] ${this.owner.name}의 공격이 빗나갔습니다.`);

         return false;
     }
 }

 

Weapon 클래스에서는 WeaponAttack() 메서드를 이용해 상대방을 공격하고,

무기 종류에 따라 상대방에게 상태이상을 적용한다.

 

🌙 하루를 마치며

캠프에서 제시한 기본과 도전은 모두 구현을 완료했다.

내일 한번 더 테스트 해서 버그가 없는지 확인하고, 제출한 뒤 캠프에서 제공한 Node.js 강의 수업을 들어야겠다.

오늘의 목표

더보기

✔️ 스탠다드 반 강의 OT

✔️ 프로그래머스 알고리즘 문제 풀이

✔️ 자바스크립트 강의 정리

❌ 개인 과제 진행


⏱️ 오늘의 일정

9:00 ~ 10:00 - 프로그래머스 알고리즘 문제 풀이
10:00 ~ 11:00 - 스탠다드 반 강의 OT

13:00 ~ 20:00 - 자바스크립트 강의 정리


📜 프로그래머스 알고리즘 문제 풀이

9:00 ~ 10:00 - 프로그래머스 알고리즘 문제 풀이

 

명예의 전당

https://github.com/YamSaeng/AlgorithmCodingTest/tree/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/1/138477.%E2%80%85%EB%AA%85%EC%98%88%EC%9D%98%E2%80%85%EC%A0%84%EB%8B%B9%E2%80%85%EF%BC%881%EF%BC%89

 

AlgorithmCodingTest/프로그래머스/1/138477. 명예의 전당 (1) at main · YamSaeng/AlgorithmCodingTest

This is an auto push repository for Baekjoon Online Judge created with [BaekjoonHub](https://github.com/BaekjoonHub/BaekjoonHub). - YamSaeng/AlgorithmCodingTest

github.com

 

📜 스탠다드 반 강의 OT

10:00 ~ 11:00 - 스탠다드 반 강의 OT

 

스탠다드 반 강의 OT 세션에 참여했다.

스탠다드 반은 CS 지식과 네트워크 지식을 강의하는 수업으로 매주 화, 목 10시에 시작한다고 공지를 받았다.

발제자 3명이 해당 주차의 주제를 각각 조사해오고 직접 발표를 한 뒤, 튜터님의 강의가 이어지는 방식으로 진행된다.

발제자 3명은 랜덤하게 돌려서 뽑는 방식이라고 하고, 발제자가 아니더라도 다른 사람들도 내용을 조사해 블로그에 게시한 후 링크를 전달해야 한다고 설명받았다.

 

📜 자바스크립트 강의 정리

13:00 ~ 20:00 - 자바스크립트 강의 정리

 

강의 시간에 배웠던 자바스크립트 강의와 수업 내용은 아니지만 필요한 내용도 함께 정리했다.

 

2024.08.22 - [Javascript/배열 ( Array )] - [Javascript] Array - 최대값, 최소값

 

[Javascript] Array - 최대값, 최소값

Array ( 배열 ) 에서 최대값과 최소값을 구하는 방법을 알아보자. Math.max(), Math.min() let maxValue = Math.max(1, 2, 3, 4, 5);let minValue = Math.min(1, 2, 3, 4, 5);console.log(maxValue); // 5console.log(minValue); // 1 Math.max()

program-yam.tistory.com

 

2024.08.22 - [Javascript/클래스( class )] - [Javascript] class

 

[Javascript] class

클래스는 객체를 생성하기 위한 템플릿으로 생각하면 된다.클래스를 생성하기 위해서는 class 키워드를 사용한다.기본 문법class MyClass { // 여러 메서드를 정의할 수 있음 constructor() { ... } method1() {

program-yam.tistory.com

 

2024.08.22 - [Javascript] - [Javascript] 프로토타입 ( Prototype )

 

[Javascript] 프로토타입 ( Prototype )

prototype 프로퍼티는 자바스크립트 내부에서 광범위하게 사용된다.모든 내장 생성자 함수에서 prototype 프로퍼티를 사용한다.Object.prototype빈 객체를 생성해보자.let obj = {};alert( obj ); // "[object Object]"

program-yam.tistory.com

 

2024.08.22 - [Javascript] - [Javascript] 화살표함수

 

[Javascript] 화살표함수

함수 표현식보다 단순하고 간결한 문법으로 함수를 만들 수 있는 방법이 있다. 바로 화살표 함수를 말하는데, 화살표 함수라는 이름은 문법의 생김새를 차용해 지어졌다.let func = (arg1, arg2, ...arg

program-yam.tistory.com

 

🌙 하루를 마치며

개인 과제도 진행을 해야하는데, 두통이 너무 심해 중간중간 약을 먹고 누워 있어서 진행을 하지 못했다.

한 2일간 계속 두통이 이어지는데 이유를 모르겠다..

 

앞서 언급했던 Node.js 강의 입문과 숙련이 모든 수강생한테 지급되었다. 

애초에 목표했던 대로 이번주 안에 과제를 제출하고 주말에 Node.js 강의를 수강하도록 해야겠다.

오늘의 목표

더보기

✔️ 알고리즘 세션 듣기

✔️ 알고리즘 도전 1일, 2일차 문제 풀기


⏱️ 오늘의 일정

9:00 ~ 10:00 - 알고리즘 세션 듣기
10:00 ~ 13:00 - 병원

13:00 ~ 16:00 - 알고리즘 도전 1일, 2일차 문제 풀기

16:00 ~ 17:00 - 자바스크립트 세션

17:00 ~ 21:00 - 알고리즘 도전 1일, 2일차 문제 풀기


📜 알고리즘 세션 듣기

9:00 ~ 10:00 - 알고리즘 세션 듣기

 

어제에 이어 오늘도 알고리즘 세션이 준비되어서 강의를 들었다.

알고리즘 문제가 제시되면 접근하는 방법과 연습문제를 제시하고 같이 풀어보는 방식으로 진행했다.

 

📜 병원

10:00 ~ 13:00 병원

 

엄마의 건강 이슈로 인해 병원에 다녀왔다.

정말 다행히도 우려했던 것과는 다르게 전달 받은 건강에 대한 정보가 너무 좋아서 한시름 놓게 되었다. 

계속 신경 쓰여서 걱정이 너무 되었는데, 온전히 공부에만 집중할 수 있을 것 같아 매우 다행이다.


📜 자바스크립트 세션

16:00 ~ 17:00 - 자바스크립트 세션

 

집에 도착해서 알고리즘 문제를 풀고 있을 때, 슬랙으로 16:00 부터 자바스크립트 세션이 있다고 전달받았다.

같이 수업받는 사람들이 공통적으로 어려워하는 부분을 파악하고, 해당 주제를 집중적으로 다루는 세션이였다.

 

this, 호이스팅, 동기, 비동기, promise 등에 관한 내용이였고, 도움이 되었다.


📜 알고리즘 도전 1일, 2일차 문제 풀기

13:00 ~ 16:00 - 알고리즘 도전 1일, 2일차 문제 풀기

17:00 ~ 21:00 -  알고리즘 도전 1일, 2일차 문제 풀기

 

어제에 이어서 알고리즘 2일차 문제 5가지가 제시되었다.

 

문제 1

주어진 문자열에서 중복된 문자를 제거하고, 남은 문자들을 원래 순서대로 반환하는 함수를 작성하세요.

제한사항:

  • 문자열의 길이는 1 이상 1000 이하입니다.

예시) const s = "abbccdeff"; // 출력 : "abcdef"

문제 2

 

주어진 배열에서 최솟값과 최댓값을 찾고, [최솟값, 최댓값] 형태의 배열을 반환하는 함수를 작성하세요.

제한사항:

  • 배열의 길이는 1 이상 1000 이하입니다.
  • 배열의 원소는 -1000 이상 1000 이하의 정수입니다.

예시) const arr = [1,2,3,4,5,6]; // 출력 [1,6]

 

문제 3

주어진 문자열을 요약하는 함수를 작성해주세요!

 

예시) str = 'aaabbbc' // 출력 : 'a3/b3/c1'

 

 

문제 4

주어진 배열에서 두 수를 선택하여 그 합이 주어진 target 값과 일치하는지 확인하는 함수를 작성하세요. 일치하는 경우 true, 그렇지 않은 경우 false를 반환하세요.

제한사항:

  • 배열의 길이는 2 이상 1000 이하입니다.
  • 배열의 원소는 1 이상 1000 이하의 자연수입니다.

예시) arr = [2,7,11,15], target = 9 // 출력 : true

 

문제 5

주어진 문자열이 유효한 괄호 조합인지 확인하는 함수를 작성하세요. 유효한 조합은 모든 여는 괄호가 올바르게 닫혀야 하며, 괄호의 순서도 일치해야 합니다.

제한사항:

  • 문자열의 길이는 1 이상 1000 이하입니다.
  • 괄호는 (), {}, []의 세 종류입니다.

예시) ({[]}] // 출력 : true

         ({][}) // 출력 : false

 


🌙 하루를 마치며

엄마 건강에 걱정이 많았는데 잘 해결된거 같아 정말 다행이다. 정말로.. ㅠㅠ

 

어제 오늘 제시된 알고리즘 10문제를 모두 풀기는 했다. 내일 9시에 있을 문제 풀이를 듣고,내가 풀이한 것과 튜터님의 풀이 방법을 비교해 글을 게시할 생각이다.

 

내일 또한 개인과제에 대한 설명이 있다고 전달 받았다. 기간은 일주일동안 과제를 풀어 제출해야한다고 하는데,자바스크립트를 처음 접해 걱정도 되고 기대도 된다.. 

 

+ Recent posts