https://github.com/tony9402/baekjoon/tree/main

 

GitHub - tony9402/baekjoon: 코딩테스트 대비 문제집(Baekjoon Online Judge)

코딩테스트 대비 문제집(Baekjoon Online Judge). Contribute to tony9402/baekjoon development by creating an account on GitHub.

github.com

 

여기서 문제를 찾아서 푸는것도 좋은것 같다.

 

https://www.acmicpc.net/problem/2753

문제

연도가 주어졌을 때, 윤년이면 1, 아니면 0을 출력하는 프로그램을 작성하시오.

윤년은 연도가 4의 배수이면서, 100의 배수가 아닐 때 또는 400의 배수일 때이다.

예를 들어, 2012년은 4의 배수이면서 100의 배수가 아니라서 윤년이다. 1900년은 100의 배수이고 400의 배수는 아니기 때문에 윤년이 아니다. 하지만, 2000년은 400의 배수이기 때문에 윤년이다.

입력

첫째 줄에 연도가 주어진다. 연도는 1보다 크거나 같고, 4000보다 작거나 같은 자연수이다.

출력

첫째 줄에 윤년이면 1, 아니면 0을 출력한다.

예제 입력 1

2000

예제 출력 1

1

예제 입력 2

1999

예제 출력 2

0

풀이

간단하게 정리하면 윤년의 조건은 두가지가 된다.

 

1. 4의 배수이면서 100의 배수가 아닌 년도

2. 4의 배수이면서 100의 배수이고, 400의 배수인 년도

 

나머지는 모두 윤년이 아니므로 0을 출력하면 된다.

배수를 구할때는 %를 사용해서 나머지가 0인 값을 찾았다.

더보기
더보기
import java.util.Scanner;

public class Main {
    public static void main(String[] args){

        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        int result = 0;

        // 4의 배수라면
        if ( num%4 == 0 ){
            // 100의 배수라면
            if ( num % 100 == 0 ) {
                if ( num % 400 == 0 ) {
                    result = 1;
                }
            } else {
                result = 1;
            }
        }
        System.out.println(result);
    }
}

'코테 > 백준' 카테고리의 다른 글

17389번 보너스 점수  (0) 2025.04.03
2798번 블랙잭  (1) 2025.02.13
3009번 네 번째 점  (1) 2025.02.11
11653번 소인수분해  (1) 2025.02.10
2581번 소수  (1) 2025.02.08

https://www.acmicpc.net/problem/17389

 

문제

OX표의 점수는 다음과 같이 계산된다.

  • OX표에 N개의 문제들이 있을 때, 1번 문제, 2번 문제, ..., N번 문제 순으로 채점된다.
  • 문제는 뒤로 갈수록 어려워지기 때문에, i 번 문제의 기본 점수는 i 점이다.
    • 문제를 맞히면 그 문제의 기본 점수(즉 i 번 문제의 경우 i 점)를 획득하며, 틀리면 얻지 못한다.
  • 기본 점수와 별개로, '보너스 점수'라는 값이 존재한다. 이는 처음에는 0점이다.
    • 문제를 맞히면 그 때의 '보너스 점수'를 획득하고, '보너스 점수'의 값이 1점 증가한다.
    • 문제를 틀리면 '보너스 점수'를 얻지 못하고, '보너스 점수'의 값이 0점으로 초기화된다.

입력

첫 번째 줄에 OX표의 길이인 자연수 N이 주어진다. (1 ≤ N ≤ 10,000)

두 번째 줄에 OX표를 의미하는 문자열 S가 주어진다. 

S는 O(알파벳 대문자 O, ASCII 코드 79)와 X(알파벳 대문자 X, ASCII 코드 88)로만 구성되어 있으며, 길이는 N이다.

문자열 S의 i 번째 글자가 O이면 해당 참가자가 i 번째 문제를 맞혔음을 의미하고, X이면 틀렸음을 의미한다.

출력

첫 번째 줄에 입력으로 들어온 OX표의 점수를 출력한다.

예제 입력

8
XOOOXOOX

예제 출력

26
 

풀이

간단하게 생각하면

 

1. 길이 n 과 문자열 s를 입력받는다.

2. 그외 초기값들을 정리한다.

3. 반복문으로 n 또는 s의 길이만큼 반복한다.

4. 문자열에서 i번째 해당하는 문자가 'O' 라면?

    4-1. 총합 = 총합  + 보너스 + (i+1) 값을 더하고, 보너스를 1 더한다

5. 만약에 아니면 보너스 값을 0으로 초기화한다.

6. 총합을 출력한다.

더보기
더보기
import java.util.Scanner;

public class Main {
    public static void main(String[] args){

        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        String str = sc.next();

        // 보너스 값 초기화
        int bouns = 0;
        int result = 0;

        for(int i = 0; i < n; i++){
            if(str.charAt(i) == 'O'){
                result = result + (i+1) + bouns;
                bouns++;
            } else{
                bouns = 0;
            }
        }
        System.out.println(result);
    }
}



'코테 > 백준' 카테고리의 다른 글

2753번 윤년 / 백준 문제 추천  (0) 2025.04.05
2798번 블랙잭  (1) 2025.02.13
3009번 네 번째 점  (1) 2025.02.11
11653번 소인수분해  (1) 2025.02.10
2581번 소수  (1) 2025.02.08

2차 팀 프로젝트 마무리

이번주 목요일에 2번째 팀 프로젝트가 끝났다.

 

제목은 '모여봄', 팀 프로젝트 모집을 위한 사이트를 개발하였다.

Spring Boot를 활용한 팀프로젝트는 두번째였고 나머지 팀원들은 해본 분도 있고 처음 해보시는 분도 있었다.

 

처음 기획했던것과 디자인이나 기능들이 조금 상이한 부분이 있지만 아무래도 첫(?) 팀 프로젝트이기도 하고,

2개월에 걸쳐서 프로젝트를 완성했기에 핵심적인 기능에 초점을 맞추고 구현하였다.

 

완성된 기능으로는 기본적인 로그인, 게시판 CRUD, 팀 프로젝트 관리 등등의 기능이 있으며

조금 더 힘을 주고 만든것은 유저관련 기능과 관리자 기능이 조금 더 완성도가 높았다.

 

나는 여기서 팀 API를 맡아서 개발하였는데, 간단한 CRUD를 활용하여 여러가지 팀 관련 기능을 구현하였다.

디자인은 처음에는 테일윈드 템플릿을 쓰기로 했었으나, 결국 프로토타입 같은 디자인으로 마무리 되었다.

 

그래도 이정도면 나름 잘 완성된 것 같아 모든 팀원들에게 감사하고 있다.

우리 팀원들이 없었으면 이렇게 단기간안에 성과를 내기는 힘들었을 것이다.

이번 프로젝트를 하면서 얻은 것

두번째 Spring Boot 프로젝트이다 보니 솔직히 조금 더 자신이 있던것도 사실이였다.

하지만 정말 오랜만에 다시 해보니 부족함이 느껴졌다.

 

그러면서 무심코 지나쳤던것에 대한 새로운 궁금증도 생겼다.

예를 들어 프론트에서 요청을 보낼때 사용하는 HTTP 메서드의 종류에는 Post, Get, Put, Delete 가 있다.

하지만 그것들이 무엇이 다른가에 대해서는 생각해본적이 없었다.

 

이번 프로젝트로 예를 들어보자면

 

Post: 게시글 작성,

Get : 게시글 가져오기

Put : 게시글 수정하기

Delete : 게시글 삭제

 

이렇게만 알고 있었다.

 

하지만 그래서 상세하게 뭐가 다른가?

Post로 게시글 수정도 가능하고 Delete 하면 안되는가?

왜 굳이 저렇게 나눠놨는가에 대한 고찰은 해본적이 없다.

 

그 이유는 다음과 같았다.

1. GET (조회)

  • 역할: 서버에서 특정 리소스의 정보를 요청할 때 사용합니다.
  • 특징:
    • 서버의 데이터를 변경하지 않고 조회만 합니다.
    • 요청에 필요한 데이터를 URL의 쿼리 파라미터에 담아 전송합니다.
    • 브라우저나 프록시 서버에 의해 캐싱될 수 있습니다.
    • 보안상 민감한 데이터를 전송하는 데는 적합하지 않습니다.
    • 멱등성을 가지기에 동일한 요청을 여러 번 보내도 결과가 같습니다.

2. POST (생성)

  • 역할: 서버에 새로운 리소스를 생성하거나 데이터를 전송할 때 사용합니다.
  • 특징:
    • 요청에 필요한 데이터를 요청 본문(body)에 담아 전송합니다.
    • 서버의 데이터를 변경합니다.
    • 캐싱되지 않습니다.
    • 멱등성을 가지지 않기에 동일한 요청을 여러 번 보내면 결과가 다를 수 있습니다.

3. PUT (수정)

  • 역할: 서버의 특정 리소스를 수정할 때 사용합니다.
  • 특징:
    • 요청에 필요한 데이터를 요청 본문에 담아 전송합니다.
    • 서버의 데이터를 변경합니다.
    • 멱등성을 가지기에 동일한 요청을 여러 번 보내도 결과가 같습니다.
    • 리소스의 전체를 변경할때 사용합니다.

4. DELETE (삭제)

  • 역할: 서버의 특정 리소스를 삭제할 때 사용합니다.
  • 특징:
    • 서버의 데이터를 삭제합니다.
    • 멱등성을 가지기에 동일한 요청을 여러 번 보내도 결과가 같습니다.

여기서 멱등성이란 여러번 연산하더라도 결과가 달라지지 않음을 의미한다.

 

추가로 이것을 찾아보면서 새롭게 알게된 HTTP 메서드도 있다.

 

  • PATCH: PUT과 마찬가지로 리소스를 수정할 때 사용하지만, 리소스의 일부만 수정할 때 사용합니다.
  • OPTIONS: 서버가 지원하는 HTTP 메서드나 기타 옵션을 요청할 때 사용합니다.
  • HEAD: GET과 동일하게 리소스를 요청하지만, 응답 본문은 받지 않고 헤더 정보만 받습니다.

이렇게 매번 당연하게 사용해오던 문법에 대해서도 의문을 가지니 그 상세한 구조나 사용법을 알 수 있었다.

이는 프로그래밍을 할 때 뿐만 아니라 다른 모든것에도 적용되는 것 같다.

 

이번 프로젝트에서는 이외에도 테일윈드의 사용법, Vue.js, CORS, SSE와 같은 기술들도 배울수 있는 귀중한 시간이였다.

자소서 이야기

이번에 프로젝트가 끝남과 동시에 지원하기로 했던 한화시스템의 자소서를 작성하기 시작하였다.

하지만 이전에도 자소서를 제대로 쓰지 못해서 좌절했던 기억이 있다.

 

실패는 성공의 어머니이고 첫술에 배부를수 없다지만 글을 쓰는것은 정말 쉽지 않았고 내 자신에 많이 화가났다.

 

나는 왜 이룬것이 없을까?

나는 왜 이렇게 글을 못쓰는것일까?

 

사실 그 이유는 간단하다.

평소에 자기자신을 소개하는 글을 써본 사람이 몇이나 될까?

 

일단 나는 자소서를 작성할때 이외에는 단 한번도 써본적도, 고민해본 적도 없다.

그러니 당연히 힘들수밖에 없고 그래서 모두들 미리미리 써놓는 연습을 하라고 하는것이다.

 

나의 경우에 생각해보면 주변에서 내게 글은 잘 쓴다고 말한다.

그도 그럴것이 나는 평소에도 책 읽기를 좋아해서 머릿속 도서관에서 상황에 맞는 글귀를 찾아내서 작성하기 때문이다.

 

이것을 자소서에 적용하여 내가 느낀 감정을 표현하자면,

자소서를 쓸 때 내 머릿속에는 그 어떤 문장도 떠오르지 않았다. 왜냐면 단 한글자도 기록되어있지 않았기 때문이다.

 

평소에 틈틈히 조금씩이라도 자기 자신을 소개하는 문장에 대해서 생각해보거나,

다른사람이 작성한 자소서를 읽어보는 노력을 했다면 이런일은 없었을 것이다.

 

이것은 비단 자소서에만 적용되는것이 아니라 코딩 테스트에도 적용된다.

코딩 테스트도 꾸준히 준비하여 머릿속에 레퍼런스를 저장하고 그에 맞춰 빠르게 정답을 맞춰내는것이 핵심이다.

 

이미 늦은것일수도 있지만 이렇게라도 뒤늦게 알아서 다행이라는 생각도 든다.

분명 주변에서도 이와 같은 조언을 많이 해주었지만 내가 그 말을 듣고 그대로 이행했다면 이 글도 안쓰고 있었을 것이다.

 

다음 주 부터는 당장 프로젝트는 없지만, 바쁜 나날이 계속될 것 같다.

하지만 이런 상황에서도 한번에 모든걸 하려하기 보단 언제나 우선순위를 정해서 정리하는것이 좋을것 같다.

 

바쁘게 흘러간 2주

원래 회고록은 일주일에 한번 쓰는것이지만 저번주는 마음의 여유도 시간적 여유도 없을만큼 바뻤다.

특별한 일이 있는것은 아니고 저번주는 팀 프로젝트 작업을 하느라 밤을 꼬박 새기도 하고 정말 많은 시간을 투자했다.

 

그러다가 문득 주변 이야기들을 들어보니 3월에는 공채기간이고 취업을 하고싶으면 이 시기를 놓치면 안된다는걸 알았다.

물론 팀 프로젝트도 중요하고 강의듣는 것도 중요하고 다른 모든 일들이 중요하지만

 

사실 이 모든게 취업 하나를 위해서 이렇게 열심히 달리고 있던게 아닌가 하는 생각이 들었다.

주객전도.  취업을 목표로 공부하고 있었지만 정작 중요한 시기가 되었을 땐 공부만 하고있는 모습을 보니 떠올랐다.

 

물론 팀 프로젝트도 정말 중요하고 이 과정에서 얻은 경험과 산출물은 자소서를 작성할때 매우 도움이 될것이다.

하지만 진짜 내가 원하고 내게 가장 중요한건 취업이지 그 과정에 있는 팀프로젝트가 아니다.

 

그래서 조금 늦었지만 프로젝트에 할당했던 시간을 좀 더 줄이고 그 시간에 자소서를 작성하기 시작했다.

또, 블로그에 작성하기로 했던 글들도 팀 프로젝트에 매진하느라 미뤘었는데 이것도 정말 중요하기 때문에

다시 이렇게 글을 쓰고 있다.

 

이전에 작성했던 우선순위표를 다시금 작성할때가 온것 같다.

 

팀 프로젝트가 왜 그리 바뻤는가?

프로젝트를 진행하면서 왜 밤을 새고 그렇게 바삐 작업했나 라는 의문이 들 수도 있다고 생각한다.

원래 프로젝트에서 나의 역할은 백엔드에선 팀 기능을 주로 맡고 이번에 프론트를 나 혼자 맡게 되었다.

 

그래서 그 책임을 다하기 위해 Vue.js에 대해서 계속 공부하고 강의를 보며 프로젝트를 따로 생성해보기도 하며

기초를 다져 이를 기반으로 팀원들이 작업할 틀을 세워나갔다.

 

그렇게 열심히 만들던 도중 중간에 팀원들의 백엔드 작업이 끝나서 프론트로 합류하기로 한 그때,

팀원과의 의사소통 부족으로 인해 내가 작성한 기반은 사용되지 않았다.

 

그것을 만들기 위해 정말 밤낮없이 열심히 작업을 했지만 내게 남은건 내가 작업하던 팀 기능에 대한 작업물만 남았다.

하지만 이를 기회로 삼아 캠프에서 하는 Vue 강의를 들으며 더 나은 코드를 작성하기 위해 노력하는 시간을 가졌다.

 

그래도 Vue를 공부하고 작업하면서 정말 많은걸 알수있었고 순수 Html, Css, Js만 쓰던 과거의 내가 미련하게 느껴졌다.

새로운 기술에 대한 호기심도 있었지만 처음부터 다시 공부해야한다는 부담감도 컷던것 같지만

결국 그 기술들은 전보다 더 나은 작업물을 만들수 있게 해주었다.

 

회고록을 마치며

비록 저번주는 회고록 작성을 못했지만 다음부터는 그런일 없도록 해야겠다.

그리고 이번 프로젝트가 거의 막바지에 다다랐으니 얼른 마무리하고 밀린만큼 블로그에 글을 써야겠다.

이때까지 무엇을 하고 배웠는가?

어느덧 3월이 되었다

나는 지금까지 대략 4개월 정도 이곳에서 지내며 공부하고 있다.

기본적인 전공 지식이라던지 여러 가지 기초를 다시 다지고 한 걸음씩 나아가고 있다고 생각한다.

 

처음에는 아는것들만 나와서 기고만장했다.

그런데 이제 점차 후반부로 갈수록 점점 기술의 심화적인 내용이라던지 완전히 새로운 내용이라던지

내가 모르는 것들이 나오니 그때부터는 남들처럼 내용을 이해하기 위해 따라가기 바빴다

 

또, 내가 그 문제에 대해서 안다고 해도 다른 사람에게 쉽게 설명하지 못한다면

그건 아직 확실히 아는 게 아니라는 것을 많이 느꼈다.

 

정말로 완벽하게 이해하고 알고 있다면, 남에게 설명하는 것 또한 쉽게 해낼 수 있었을 것이다

하지만 나는 그런 질문에 잘 대답하지 못하고 지금도 쉽지는 않으니 아직 완벽히 내 것이 되었다고 할 순 없다.

 

그래서 노트에 정리하고 그 내용을 블로그에 다시 올려서 한 번씩 다시 보긴 하지만

노트에 정리한 것도 그 당시에 내가 쓴 글을 이후의 내가 봤을 때 이해하지 못한다면, 그것 또한 잘 못쓴 정리라고 생각한다.

 

이번에 블로그에 글을 작성하면서도 많이 배웠다.

남들이 보고 쉽게 이해할 수 없는 글이라면 내가 봐도 이해하기 쉽지 않은 글이고,

그것을 쉽게 풀어 정리하는 것도 하나의 공부라는 것을

 

PCCE를 도전해 보다

이번에 매달 프로그래머스에서 진행하는 코딩필수역량인증(PCCE)을 신청하여 시험을 쳐보았다.

이 전에도 기회는 있었지만 번번이 자신감 부족 및 타이밍을 놓쳐서 신청을 하지 못했었지만

이번에 한번 어떤 시험인지 체험해 보자 라는 느낌으로 도전해 보았다.

 

시험 자체는 그렇게 어렵지는 않았고 문제를 상세히 나열할 순 없지만 대략적으로 봤을 때백준 브론즈에서 잘 쳐주면 실버까지의 문제들이었던 것 같다.

 

물론 10문제 중에서 8문제를 풀었고, 합격은 했는데 Lv1 이 나왔다.내가 그 시험을 치면서 느낀 점은 이전에 코테 문제를 매일 풀었던 것이 헛수고가 아니었음을그리고 그걸 정리하고 다시 돌아보는 것도 정말 중요함을 느꼈다.

 

특히나 이러한 코테에서는 자동완성 기능이 있는 편리한 IDE를 쓰지 못하고함수를 내가 기억하고 있어야지만 작성할 수 있었다는 것에서 조금 어려웠다.

 

솔직히 말해서 너무 자동완성이나 이런 IDE에서 제공해 주는 편의성 기능에 의존하다 보니부끄럽지만 기본적인 함수마저 헷갈렸기에 마지막 두 문제는 풀지 못했다.

 

이번 시험으로 확실하게 알게 된 것은물론 코딩을 할 때 내 지식과 모든 기술을 총 동원해서 코딩하는 건 맞지만,적어도 코테를 준비한다면, 순수하게 메모장이라도 아니 그냥 종이에라도 바로 적어 낼 수 있을 정도로몸에 그냥 익히는 게 나을 것 같다는 생각이 들었다.

 

또 개인적으로 CS 지식이 많이 부족하다고 느껴 따로 책을 읽어보고 있다.내가 부족한 부분을 깨닫고 그 부분을 채우기 위해서 할 수 있는 일을 찾는 게 가장 중요하다고 생각한다.작은 도전이지만 점점 쌓이다 보면 코테 문제를 풀 때처럼 언젠가는 자연스럽게 성장할 것이라 믿는다.

  • URL 할당 및 통합
  • 8개 기능 추가

1. GET/team/find모든 팀 조회 메서드

더보기

모든 팀을 조회할 수 있는 메서드가 없었기 때문에 새로 추가하였다.

  • 컨트롤러
/**
 *
 * @param teamName      (필터) 팀 이름
 * @param teamIntroduce (필터) 팀 상세
 * @param projectStatus (필터) 팀 상태
 * @param page          최소 출력 값
 * @param size          최대 출력 값
 * @return PageImpl     필터링 결과값 반환
 */
@GetMapping("/find")
@Operation(summary = "모든 팀 조회 메서드", description = "모든 팀을 조회하는 메서드 입니다.")
@Parameters({
        @Parameter(name = "teamName" , description = "팀 이름"),
        @Parameter(name = "teamIntroduce" , description = "팀 설명"),
        @Parameter(name = "projectStatus" , description = "프로젝트 상태"),
        @Parameter(name = "page" , description = "페이지 번호", example = "1"),
        @Parameter(name = "size" , description = "한 페이지 결과 수", example = "10")
})
public ResponseEntity<PageImpl<TeamResponseDto>> getTeams(
        @RequestParam(required = false)  String teamName,
        @RequestParam(required = false)  String teamIntroduce,
        @RequestParam(required = false)  ProjectStatus projectStatus,
        @RequestParam int page,
        @RequestParam int size){

    PageImpl<TeamResponseDto> teamSearch =
            teamService.allUserTeams(teamName, teamIntroduce, projectStatus, page, size);

    return ResponseEntity.status(HttpStatus.OK). body(teamSearch);
}
  • 서비스 상세
/**
 * 모든 팀 정보 조회
 * @param teamName      (필터) 팀 이름
 * @param teamIntroduce (필터) 팀 상세
 * @param projectStatus (필터) 팀 상태
 * @param page          최소 출력 값
 * @param size          최대 출력 값
 * @return PageImpl     필터링 결과값 반환
 */
public PageImpl<TeamResponseDto> allUserTeams(
        String teamName, String teamIntroduce, ProjectStatus projectStatus, int page, int size) {
    Pageable pageable = PageRequest.of(page, size);
    Page<TeamResponseDto> teams = teamUserRepository.findByStatusForTeams(projectStatus, pageable);

    List<TeamResponseDto> filteredTeams = teams.stream()
            .filter(team -> teamName == null || team.getTeamName().contains(teamName))
            .filter(team -> teamIntroduce == null || team.getTeamIntroduce().contains(teamIntroduce))
            .filter(team -> projectStatus == null || team.getProjectStatus().equals(projectStatus))
            .toList();

    return new PageImpl<>(filteredTeams, pageable, teams.getTotalElements());
}

 

  • 리포지토리
/**
 * 모든 팀 정보 조회
 * @param status  (필터) 팀 상태
 * @param pageable 페이징 크기
 * @return TeamResponseDto
 */
@Query("SELECT new com.beyond.backend.data.dto.teamDto.TeamResponseDto" +
        "(t.no, t.teamName, t.teamIntroduce, t.projectStatus, t.timePeriod) " +
        "FROM Team t " +
        "WHERE (:status IS NULL OR  t.projectStatus = :status)")
Page<TeamResponseDto> findByStatusForTeams(@Param("status") ProjectStatus status, Pageable pageable);
  • @Param("status") 의 값이 있다면 조건 검색, 없다면 모든 검색 결과 반환

2. GET/team/find/team팀원 목록 조회 메서드

더보기

해당 팀의 팀원들의 목록을 조회하는 메서드이다.

  • 컨트롤러
/**
 * 팀원 목록 조회 메서드
 * @param teamNo 팀번호
 * @return TeamMemberListDto
 * @throws Exception 팀이 존재하지 않습니다.
 */
@GetMapping("/find/team")
@Operation(summary = "팀원 목록 조회 메서드", description = "팀원 목록 조회 메서드입니다.")
@Parameters({@Parameter(name = "teamNo" , description = "팀 번호", example = "1")})
public ResponseEntity<List<TeamMemberListDto>> getUserTeams( @RequestParam Long teamNo ) throws Exception {
    List<TeamMemberListDto> teamMembers = teamService.getTeamMembers(teamNo);

    return ResponseEntity.status(HttpStatus.OK).body(teamMembers);
}

 

  • 서비스
/**
 * 팀원 목록 조회 서비스
 *
 * @param teamNo 팀번호
 * @return TeamMemberListDto
 * @throws Exception 팀이 존재하지 않습니다.
 */
@Override
public List<TeamMemberListDto> getTeamMembers(Long teamNo) throws Exception {
    teamRepository.findById(teamNo)
            .orElseThrow(() -> new IllegalArgumentException("팀이 존재하지 않습니다."));

    return teamUserRepository.findByTeamNoForNonLeader(teamNo);
}

 

  • 리포지토리
/**
 * 모든 팀 정보 조회
 * @param status  (필터) 팀 상태
 * @param pageable 페이징 크기
 * @return TeamResponseDto
 */
@Query("SELECT new com.beyond.backend.data.dto.teamDto.TeamResponseDto" +
        "(t.no, t.teamName, t.teamIntroduce, t.projectStatus, t.timePeriod) " +
        "FROM Team t " +
        "WHERE (:status IS NULL OR  t.projectStatus = :status)")
Page<TeamResponseDto> findByStatusForTeams(@Param("status") ProjectStatus status, Pageable pageable);

3. GET/team/find/user해당 유저의 모든 팀 조회 메서드

더보기

리포지토리의 SQL 쿼리에서 불필요한 JOIN문을 지웠다.

4

/**
 * 유저가 활동한 모든 팀 조회
 * @param userNo 유저번호
 * @param pageable 페이징 크기
 * @return TeamSearchDto
 */
@Query("SELECT new com.beyond.backend.data.dto.teamDto.TeamResponseDto" +
        "(t.no, t.teamName, t.teamIntroduce, t.projectStatus, t.timePeriod) " +
        "FROM Team t " +
        "JOIN t.teamUsers tu " +
        "WHERE tu.user.no = :userNo")
Page<TeamResponseDto> findByUserNoForUserTeams(@Param("userNo") Long userNo, Pageable pageable);

4. POST/team/joinRequest팀원 가입 신청 메서드

더보기

팀원이 가입 신청을 하면 중간 테이블에 등록 하도록 하였다.

  • 컨트롤러
/**
 * 팀원 가입 신청 메서드
 * @param teamNo 팀번호
 * @param userNo 유저번호
 * @return 없음
 * @throws Exception 팀이 존재하지 않습니다.
 * @throws Exception 유저가 존재하지 않습니다.
 * @throws Exception 모집중이 아닙니다!
 * @throws Exception 이미 등록되었거나 요청한 팀 입니다!!
 */
@PostMapping("/joinRequest")
@Operation(summary = "팀원 가입 신청 메서드", description = "팀원 가입 신청 메서드입니다.")
@Parameters({
        @Parameter(name = "teamNo" , description = "팀 번호", example = "1"),
        @Parameter(name = "userNo" , description = "유저 번호")
})
public ResponseEntity<String> teamJoinRequest (@RequestParam Long teamNo,
                                               @RequestParam Long userNo) throws Exception {
    teamService.teamJoinRequest(teamNo, userNo);

    return ResponseEntity.status(HttpStatus.OK).body("정상적으로 신청되었습니다.");
}

 

  • 서비스
/**
 * 팀원 신청
 *
 * @param teamNo 팀번호
 * @param userNo 유저번호
 * @throws Exception 팀이 존재하지 않습니다.
 * @throws Exception 유저가 존재하지 않습니다.
 * @throws Exception 모집중이 아닙니다!
 * @throws Exception 이미 등록되었거나 요청한 팀 입니다!!
 */
@Override
public void teamJoinRequest(Long teamNo, Long userNo) throws Exception {

    if (teamUserRepository.findByUserNoEquals(teamNo, userNo)) {
        throw new IllegalArgumentException("이미 등록되었거나 요청한 팀 입니다!!");
    }

    com.beyond.backend.data.entity.Team Team = teamRepository.findById(teamNo)
            .orElseThrow(() -> new IllegalArgumentException("팀이 존재하지 않습니다."));
    User user = userRepository.findById(userNo)
            .orElseThrow(() -> new IllegalArgumentException("유저가 존재하지 않습니다."));

    if (Team.getProjectStatus() != ProjectStatus.OPEN) {
        throw new IllegalArgumentException("모집중이 아닙니다!");
    }

    TeamUser teamUser = TeamUser.builder()
            .user(user)
            .team(Team)
            .status(false)
            .isLeader(false)
            .build();
    teamUserRepository.save(teamUser);
}

다양한 예외 처리를 하였는데 이를 하나로 통일해서 관리하면 좋을 것 같다.

 

  • 리포지토리
/**
 * 유저가 팀에 속해있는지 여부
 * @param teamNo 팀번호
 * @param userNo 유저번호
 * @return Boolean
 */
@Query("SELECT COUNT(tu) > 0 " +
        "FROM TeamUser tu " +
        "WHERE tu.team.no = :teamNo AND tu.user.no = :userNo ")
Boolean findByUserNoEquals (@Param("teamNo") Long teamNo, @Param("userNo") Long userNo);

5. DELETE/team/joinRequestCancel팀원 가입 취소 메서드

더보기

팀원이 가입 취소 버튼을 누르면 중간 테이블에서 삭제하는 메서드이다

이를 활용하면 팀원 개인이 스스로 탈퇴할 수 있다.

  • 컨트롤러
/**
 * 팀원 가입 취소 메서드
 * @param teamNo 팀번호
 * @param userNo 유저번호
 * @return 없음
 * @throws Exception 신청하지 않았거나 존재하지 않는 팀입니다.
 */
@PDeleteMapping("/joinRequestCancel")
@Operation(summary = "팀원 가입 취소 메서드", description = "팀원 가입 취소  메서드입니다.")
@Parameters({
        @Parameter(name = "teamNo" , description = "팀 번호", example = "1"),
        @Parameter(name = "userNo" , description = "유저 번호")
})
public ResponseEntity<String> teamJoinRequestCancel (@RequestParam Long teamNo,
                                                     @RequestParam Long userNo) throws Exception {
    teamService.teamJoinRequestCancel(teamNo, userNo);

    return ResponseEntity.status(HttpStatus.OK).body("정상적으로 취소되었습니다.");
}

 

  • 서비스
/**
 * 팀원 취소
 * @param teamNo 팀번호
 * @param userNo 유저번호
 * @throws Exception 신청하지 않았거나 존재하지 않는 팀입니다.
 */
@Override
public void teamJoinRequestCancel(Long teamNo, Long userNo) throws Exception {
    Long teamUserNo = teamUserRepository.findByUserNoForTeamUserNo(teamNo, userNo);
    if (teamUserNo == null) {
        throw new IllegalArgumentException("신청하지 않았거나 존재하지 않는 팀입니다.");
    } else {
        teamUserRepository.deleteById(teamUserNo);
    }
}

 

6. GET/team/member/setting[팀장] 팀원 신청 목록 조회

더보기

팀장이 승인 여부가 ‘F’인 팀원들에 대한 목록을 조회하는 기능

  • 컨트롤러
/**
 * [팀장] 팀원 신청 목록 조회
 * @param teamNo 팀번호
 * @param userNo 유저번호
 * @return TeamMemberListDto
 * @throws Exception 권한이 없습니다!
 */
@GetMapping("/member/setting")
@Operation(summary = "[팀장] 팀원 신청 목록 조회", description = "팀원 신청 목록 조회 메서드입니다.")
@Parameters({
        @Parameter(name = "teamNo" , description = "팀 번호", example = "1"),
        @Parameter(name = "userNo" , description = "팀장 번호", example = "1")
})
public ResponseEntity<List<TeamMemberListDto>> getMemberRequest(
        @RequestParam Long teamNo,
        @RequestParam Long userNo) throws Exception {
    List<TeamMemberListDto> teamMemberRequest = teamService.getTeamMemberRequest(teamNo, userNo);

    return ResponseEntity.status(HttpStatus.OK).body(teamMemberRequest);
}

 

  •  서비스
/**
 * [팀장] 팀원 신청 목록 조회
 *
 * @param teamNo 팀번호
 * @param userNo 유저번호
 * @return TeamMemberListDto
 * @throws Exception 권한이 없습니다!
 */
@Override
public List<TeamMemberListDto> getTeamMemberRequest(Long teamNo, Long userNo) throws Exception {
    Boolean isLeader = teamUserRepository.isLeader(teamNo, userNo);
    if (isLeader != null && isLeader) {
        return teamUserRepository.findByTeamNoForMemberRequest(teamNo);
    } else {
        throw new IllegalArgumentException("권한이 없습니다!");
    }
}

 

7. PUT/team/member/setting/teamAccept[팀장] 팀원 가입 수락

더보기

팀장이 승인 여부가 ‘F’인 회원을 승인 여부 ‘T’로 저장 → 팀원 추가

  • 컨트롤러
/**
 * [팀장] 팀원 가입 수락 메서드
 * @param teamNo 팀번호
 * @param userNo 신청한 유저의 유저번호
 * @return 정상적으로 수락되었습니다.
 * @throws Exception 신청한 유저가 없습니다!
 * @throws Exception 이미 가입된 유저입니다!
 */
@PutMapping("/member/setting/teamAccept")
@Operation(summary = "[팀장] 팀원 가입 수락 메서드", description = "팀원 가입 수락 메서드입니다.")
@Parameters({
        @Parameter(name = "teamNo" , description = "팀 번호", example = "1"),
        @Parameter(name = "userNo" , description = "유저 번호")
})
public ResponseEntity<String> teamAccept (@RequestParam Long teamNo,
                                          @RequestParam Long userNo) throws Exception {
    teamService.teamAccept(teamNo, userNo);

    return ResponseEntity.status(HttpStatus.OK).body("정상적으로 수락 되었습니다.");
}

 

  •  서비스
/**
 * [팀장] 팀원 가입 수락
 * @param teamNo 팀번호
 * @param userNo 신청한 유저의 유저번호
 * @throws Exception 신청한 유저가 없습니다!
 * @throws Exception 이미 가입된 유저입니다!
 */
@Override
public void teamAccept(Long teamNo, Long userNo) throws Exception {
    Long teamUserNo = teamUserRepository.findByUserNoForTeamUserNo(teamNo, userNo);

    TeamUser teamUser = teamUserRepository.findById(teamUserNo)
            .orElseThrow(() -> new IllegalArgumentException("신청한 유저가 없습니다!"));

    boolean status = teamUser.isStatus();
    if (status) {
        throw new IllegalArgumentException("이미 가입된 유저입니다!");
    }else {
        teamUser.setStatus(true);
        teamUserRepository.save(teamUser);
    }
}

 

8. DELETE/team/member/setting/teamDelete[팀장] 팀원 가입 거부

더보기

팀장이 중간 테이블에서 팀원을 제거한다. 추방 기능으로 활용도 가능하지만 보류

  • 컨트롤러
/**
 * [팀장] 팀원 가입 거부 메서드
 * @param teamNo 팀번호
 * @param userNo 신청한 유저의 유저번호
 * @return 정상적으로 처리 되었습니다.
 * @throws Exception 신청한 유저가 없습니다!
 */
@DeleteMapping("/member/setting/teamDelete")
@Operation(summary = "[팀장] 팀원 가입 거부 메서드", description = "팀원 가입 거부 메서드입니다.")
@Parameters({
        @Parameter(name = "teamNo" , description = "팀 번호", example = "1"),
        @Parameter(name = "userNo" , description = "유저 번호")
})
public ResponseEntity<String> teamDelete(@RequestParam Long teamNo,
                                         @RequestParam Long userNo) throws Exception {
    teamService.teamDelete(teamNo, userNo);

    return ResponseEntity.status(HttpStatus.OK).body("정상적으로 처리 되었습니다.");
}

 

  •  서비스
/**
 * [팀장] 팀원 신청 거부
 * @param teamNo 팀번호
 * @param userNo 신청한 유저의 유저번호
 * @throws Exception 신청한 유저가 없습니다!
 */
@Override
public void teamDelete(Long teamNo, Long userNo) throws Exception {
    Long teamUserNo = teamUserRepository.findByUserNoForTeamUserNo(teamNo, userNo);

    TeamUser teamUser = teamUserRepository.findById(teamUserNo)
            .orElseThrow(() -> new IllegalArgumentException("신청한 유저가 없습니다!"));

    boolean status = teamUser.isStatus();
    if (!status) {
        teamUserRepository.deleteById(teamUserNo);
    }
    // 추방도 가능하지만 일방적인 추방 기능은 논의해봐야할듯
    // 현재는 유저 스스로 나가는것만 가능
}

이후에 URL 수정을 해주었다.

더보기

DELETE/team/{teamNo}/join-cancel**팀원 가입 취소 메서드

POST/team/{teamNo}/join-request**팀원 가입 신청 메서드

DELETE/team/{teamNo}/setting/delete**팀 삭제 메서드

GET/team/{teamNo}/setting/members[팀장] 팀원 신청 목록 조회

PUT/team/{teamNo}/setting/members/accept/{userNo}[팀장] 팀원 가입 수락 메서드

PUT/team/{teamNo}/setting/members/delete/{userNo}[팀장] 팀원 가입 거부 메서드

GET/team/{teamNo}/setting/members/find**팀원 목록 조회 메서드

PUT/team/{teamNo}/setting/update**팀 수정 메서드

POST/team/create**팀 생성 메서드

GET/team/find**해당 유저의 모든 팀 조회 메서드

하지만 RESTFul 하지 않기 때문에 다시 수정해야한다.

'백엔드 > Spring Boot' 카테고리의 다른 글

모여봄 #4 팀 조회 페이징 추가  (0) 2025.03.08
모여봄 #3 팀 조회 기능  (1) 2025.03.08
모여봄 #2 CRUD 구현  (0) 2025.03.02
모여봄 #1 프로젝트 구상  (0) 2025.02.23

전체적으로 Page 타입으로 반환하도록 수정하고,

Pageable<page(최소), size(최대)> 값을 매개변수로 받게 수정함

 

- TeamRepository 변경

더보기
public interface TeamRepository extends JpaRepository<Team, Long> {

    @Query("SELECT new com.beyond.backend.data.dto.TeamSearchDto(t.teamName, t.teamIntroduce, t.projectStatus, t.timePeriod.createdAt) " +
            "FROM User u " +
            "JOIN TeamUser tu ON u.no = tu.user.no " +
            "JOIN Team t ON tu.team.no = t.no " +
            "WHERE u.no = :userNo")
    Page<TeamSearchDto> findUserTeams(@Param("userNo") Long userNo, Pageable pageable);
}

- TeamSercviceImpl 변경

더보기
/**
 * userNo로 팀 정보 조회 서비스
 *
 * @param userNo 유저 번호
 * @param teamName (필터) 팀이름
 * @param teamIntroduce (필터) 팀 설명
 * @param projectStatus (필터) 팀 상태
 * @param page 최소 출력 값
 * @param size 최대 출력 값
 * @return PageImpl 필터링 결과값 반환
 */
@Override
public Page<TeamSearchDto> filterUserTeams(
        Long userNo, String teamName, String teamIntroduce, String projectStatus, int page, int size){
    Pageable pageable = PageRequest.of(page, size);
    Page<TeamSearchDto> teams = teamRepository.findUserTeams(userNo, pageable);

    List<TeamSearchDto> filteredTeams = teams.stream()
            .filter(team -> teamName == null || team.getTeamName().contains(teamName))
            .filter(team -> teamIntroduce == null || team.getTeamIntroduce().contains(teamIntroduce))
            .filter(team -> projectStatus == null || team.getProjectStatus().equals(projectStatus))
            .toList();
    return new PageImpl<>(filteredTeams, pageable, teams.getTotalElements());
}
- return new PageImpl<>(반환 요소, 범위 , 전체 크기);

- TeamService 변경

더보기
Page<TeamSearchDto> filterUserTeams(
        Long userNo, String teamName,
        String teamIntroduce, String projectStatus,
        int page, int size);

- TeamController 변경

더보기
/**
 * userNo로 팀 정보를 조회하는 메서드
 *
 * @param userNo 유저 번호
 * @param teamName (검색용) 팀이름
 * @param teamIntroduce (검색용) 팀 설명
 * @param projectStatus (검색용) 팀 상태
 * @param page 최소 출력 값
 * @param size 최대 출력 값
 * @return teamSearch 검색 결과값 반환
 */
@Operation(summary = "팀 조회 메서드", description = "유저 번호로 해당 유저의 모든 팀을 조회하는 메서드 입니다.")
@GetMapping()
public ResponseEntity<Page<TeamSearchDto>> getUserTeams(
        @RequestParam Long userNo,
        @RequestParam(required = false)  String teamName,
        @RequestParam(required = false)  String teamIntroduce,
        @RequestParam(required = false)  String projectStatus,
        @RequestParam int page,
        @RequestParam int size){

    Page<TeamSearchDto> teamSearch = teamService.filterUserTeams(userNo, teamName, teamIntroduce, projectStatus, page, size);

    return ResponseEntity.status(HttpStatus.OK).body(teamSearch);
}

'백엔드 > Spring Boot' 카테고리의 다른 글

모여봄 #4 팀 관련 추가 기능들 구현  (0) 2025.03.08
모여봄 #3 팀 조회 기능  (1) 2025.03.08
모여봄 #2 CRUD 구현  (0) 2025.03.02
모여봄 #1 프로젝트 구상  (0) 2025.02.23

기본 동작 정리


  1. userNo를 사용하여 기본적인 팀 정보를 모두 가져옴
  2. 옵션을 사용한다면 해당 정보에서 동적 쿼리 필터링을 해서 반환

로직

  • userNo는 사용자가 로그인하면 기본적으로 가져올수 있는 값이므로 해당 값을 인자로 받는 쿼리를 생성해야함
    • 해당 쿼리문은 users - teamuser - team 이렇게 조인해줘야함
    • 조인해서 userNo를 where 조건을 걸어서 모두 반환
  • 해당 쿼리를 옵션이 없다면 그대로 반환하고 있다면 동적으로 필터링해야함
  • 컨트롤러에선 결과만 반환해야함

구현

  • TeamUser 엔티티
더보기
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "team_user")
public class TeamUser {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long no;

    @ManyToOne
    @JoinColumn(name = "user_no", nullable = false)
    private User user;

    @ManyToOne
    @JoinColumn(name = "team_no", nullable = false)
    private Team team;

    @Column(nullable = false)
    private boolean status; // 승인여부

    @Column
    private String role;
}
  • TeamSearchDto
더보기
@Data
@Builder
public class TeamSearchDto {

    private String teamName;

    private String teamIntroduce;

    private ProjectStatus projectStatus;

    private LocalDateTime createdAt;

}
  •  TeamRepository
더보기
public interface TeamRepository extends JpaRepository<Team, Long> {

    @Query("SELECT new com.beyond.backend.data.dto.TeamSearchDto(t.teamName, t.teamIntroduce, t.projectStatus, t.timePeriod.createdAt) " +
            "FROM User u " +
            "JOIN TeamUser tu ON u.no = tu.user.no " +
            "JOIN Team t ON tu.team.no = t.no " +
            "WHERE u.no = :userNo")
    List<TeamSearchDto> findUserTeams(@Param("userNo") Long userNo);
}
  • userNo로 team 정보 가져오기
  • 현재 작성한 쿼리문은 JPQL (Java Persistence Query Language)
  • DSL (Domain-Specific Language) - QueryDSL 를 사용해보는 것을 고려
  • 더보기
    • JPQL:
      • SQL과 유사한 문법.
      • 문자열 기반.
      • 런타임 시에 타입 검사.
      • SQL에 익숙한 개발자에게 직관적.
    • QueryDSL:
      • 메서드 체인 방식의 DSL.
      • 자바 코드로 쿼리 작성.
      • 컴파일 시에 타입 검사.
      • 유지보수 용이.
      • 타입 안전성 높음. 차이점
  • TeamServiceImpl
    • filter를 사용해서 값이 null이면 그대로 반환, null이 아니면 해당 값으로 필터링 한 값을 반환
더보기
@Override
public List<TeamSearchDto> filterUserTeams(Long userNo, String teamName, String teamIntroduce, String projectStatus){
    List<TeamSearchDto> teams = teamRepository.findUserTeams(userNo);

    List<TeamSearchDto> filteredTeams = teams.stream()
            .filter(team -> teamName == null || team.getTeamName().contains(teamName))
            .filter(team -> teamIntroduce == null || team.getTeamIntroduce().contains(teamIntroduce))
            .filter(team -> projectStatus == null || team.getProjectStatus().equals(projectStatus))
            .toList();
    return filteredTeams;
}
  • TeamController
    • userNo는 무조건 받고 나머지 값은 필수가 아님
더보기
@GetMapping()
public ResponseEntity<List<TeamSearchDto>> getUserTeams(
        @RequestParam Long userNo,
        @RequestParam(required = false)  String teamName,
        @RequestParam(required = false)  String teamIntroduce,
        @RequestParam(required = false)  String projectStatus){

    return ResponseEntity.status(HttpStatus.OK).body(teamService.filterUserTeams(userNo, teamName, teamIntroduce, projectStatus));
}

노션에 정리했던 글을 옮겨왔는데 가독성이 많이 떨어지는 것 같다..

어떻게 하면 더 정리를 잘 할수 있을까

'백엔드 > Spring Boot' 카테고리의 다른 글

모여봄 #4 팀 관련 추가 기능들 구현  (0) 2025.03.08
모여봄 #4 팀 조회 페이징 추가  (0) 2025.03.08
모여봄 #2 CRUD 구현  (0) 2025.03.02
모여봄 #1 프로젝트 구상  (0) 2025.02.23

Vue를 사용하는 이유

  • 자바스크립트 DOM을 사용하는 것은 매우 피곤한 작업인데 이런 작업을 쉽게 할 수 있음
  • 동적 데이터 처리를 수월하게 수행 가능
  • 컴포넌트 기반으로 UI 요소들을 모듈화 할 수 있음
  • Vue에서 제공하는 디렉티브들도 조건문이나 반복문 등을 쉽게 구현가능함
  • 가볍고 성능이 좋음

Vue.js의 프로젝트 구조

.
├── public
│   ├── index.html
│   └── ...
├── src
│   ├── assets
│   │   └── ... (이미지, 스타일 파일 등)
│   ├── components
│   │   └── ... (공통으로 사용하는 컴포넌트)
│   ├── views
│   │   └── ... (각 페이지 컴포넌트)
│   ├── router
│   │   └── index.js (라우터 설정)
│   ├── store
│   │   └── index.js (Vuex 상태 관리)
│   ├── App.vue
│   ├── main.js (진입 파일)
│   └── ...
├── package.json
└── ...

프로젝트 구조 설명

  • public: 정적 파일이 위치하는 디렉토리로, index.html 파일이 포함됩니다.
  • src: 소스 코드가 포함된 디렉토리로, 프로젝트의 핵심 부분입니다.
    • assets: 이미지, 스타일 파일 등 정적 자원이 포함됩니다.
    • components: 재사용 가능한 컴포넌트가 포함됩니다.
    • views: 페이지 단위의 컴포넌트가 포함됩니다.
    • router: Vue Router 설정 파일이 포함됩니다.
    • store: Vuex 상태 관리 파일이 포함됩니다.
    • App.vue: 최상위 컴포넌트입니다.
    • main.js: 애플리케이션의 진입 파일로, Vue 인스턴스를 생성하고 설정하는 파일입니다

설치

  • node.js LTS 버전 설치
 

Node.js — Node.js® 다운로드

Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.

nodejs.org

  • VSCode
 

Visual Studio Code - Code Editing. Redefined

Visual Studio Code redefines AI-powered coding with GitHub Copilot for building and debugging modern web and cloud applications. Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows.

code.visualstudio.com

 

  1. VSCode의 터미널 창에서 vue cli 개발환경 설정 도구 설치
npm install -g @vue/cli

 

  • 아래와 같은 오류가 뜬다면
npm : 이 시스템에서 스크립트를 실행할 수 없으므로 C:\Program Files\nodejs\npm.ps1 파일을 로드할 수 없습니다. 자세한 내용은 about_Execution_Policies(https://go.microsoft.com/fwlink/?LinkID=13517 0)를 참조하십시오. 위치 줄:1 문자:1 + npm install -g @vue/cli + ~~~ + CategoryInfo : 보안 오류: (:) [], PSSecurityException + FullyQualifiedErrorId : UnauthorizedAccess
  • PowerShell을 관리자 권한으로 실행하고 아래 코드를 입력
Set-ExecutionPolicy Unrestricted

 

 

  2. 확장 기능 설치

  • Vue - Official
  • vue3-snippets-for-vscode (코드 자동완성 기능)
  • (추천) Material Icon Theme (폴더 아이콘)

 

   3.  프로젝트 생성

vue create [프로젝트 명]

 

 

  4. 프로젝트 생성 후 프로젝트 폴더로 이동

cd [프로젝트명]
code . # 새 창에서 열기

'프론트 > Vue 3' 카테고리의 다른 글

[Vue3] 0. 정리하기 앞서  (0) 2025.03.02

앞으로 작성될 글들에서 기초 부분은 아래의 유튜브 영상을 보고 공부하였다.

여기서 배운 내용들과 추가로 공부한 내용들을 기록하기 위해 글을 작성한다.

https://youtu.be/m2j_Y245xew

 

또한 공식문서에도 많은 자료가 있다.

https://ko.vuejs.org/guide/introduction.html

 

Vue.js

Vue.js - 프로그래시브 자바스트립트 프레임워크

ko.vuejs.org

 

'프론트 > Vue 3' 카테고리의 다른 글

[Vue3] 1. Vue를 사용하는 이유와 설치방법  (1) 2025.03.02

+ Recent posts