🙋 Springboot, JPA를 활용하여 프로젝트를 만들 때 어떤 순서로 생성할지 참고해보기.

 

1. 프로젝트 생성 :

  • IntelliJ IDEA에서 새로운 스프링 부트 프로젝트를 생성한다. IntelliJ IDEA에서는 "File" -> "New" -> "Project..."를 선택한 후, "Spring Initializr"를 선택하여 프로젝트를 생성할 수 있다.
  • (또는 https://start.spring.io/ 가서 Spring Initializr 직접 사용하여 가져오기는 방법도 있다.)

2.프로젝트 구성 :

  • 프로젝트 구성에서는 사용할 언어, 스프링 부트 버전, 그리고 프로젝트의 기본 설정을 지정한다. JPA를 사용하기 위해 "Spring Data JPA"를 선택하고, 필요에 따라 다른 의존성도 추가한다.(ex. Spring Web)

3. 데이터베이스 설정 :

  • application.properties 또는 application.yml 파일을 이용하여 데이터베이스 연결 정보를 설정한다. 데이터베이스 종류, URL, 사용자명, 암호 등을 지정한다.

4. 엔티티 클래스 생성 :

  • JPA를 사용하여 데이터베이스와 상호작용하기 위해 엔티티 클래스를 생성한다. 이 클래스는 데이터베이스의 테이블과 매핑되어야 한다.
  • 예시 코드(ex. 게시글을 나타내는 Post 엔티티)
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Post {

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

    private String title;
    private String content;

    // Getters and setters, constructors, and other methods

}

 

5. 리포지토리 인터페이스 생성 :

  • JPA 리포지토리 인터페이스를 생성하여 데이터베이스 조작을 위한 메서드를 정의한다. 스프링 부트의 Spring Data JPA는 이 인터페이스를 구현해주는 프록시 객체를 생성한다.
  • 예시 코드
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;

public interface PostRepository extends JpaRepository<Post, Long> {
    
    // 제목에 특정 키워드가 포함된 게시글 검색
    List<Post> findByTitleContaining(String keyword);

    // 사용자명으로 게시글 찾기
    List<Post> findByAuthor(String author);

    // 제목과 내용에 특정 키워드가 포함된 게시글 찾기
    List<Post> findByTitleContainingOrContentContaining(String title, String content);
}
  • 여기서 PostRepository는 JpaRepository를 확장하고 있어서, 별도의 구현체 없이도 기본적인 CRUD 기능을 사용할 수 있습니다. JpaRepository는 기본적인 CRUD 외에도 다양한 메서드들을 제공합니다.
  • 위의 코드에서 Post는 엔터티 클래스이며, Long은 엔터티의 식별자(ID)의 타입입니다. 

6. 서비스 및 컨트롤러 생성 :

  • 서비스 클래스에서는 비즈니스 로직을 정의하고, 컨트롤러에서는 클라이언트 요청에 대한 핸들링을 수행한다.

7. 웹 페이지 작성 :

  • Thymeleaf, FreeMarker 등을 사용하여 웹 페이지를 작성하고, 컨트롤러에서 이를 렌더링하여 사용자에게 보여준다.

8. 프로젝트 실행 및 테스트 :

  • IntelliJ IDEA에서 스프링 부트 애플리케이션을 실행하고, 브라우저 또는 API 테스트 도구를 사용하여 게시판이 제대로 작동하는지 확인한다.

9. 기능 확장 :

  • 기본적인 CRUD(Create, Read, Update, Delete) 기능을 구현한 후, 검색, 정렬, 페이징과 같은 추가적인 기능을 구현해본다.

🙋 MySQL 8.2 Command Line Client 프로그램 클릭 시 창이 켜졌다가 바로 꺼지는 현상 해결하는 방법

1. MySQL 8.2 Command Line Client 프로그램 '속성' 창 열기

 

2. 바로가기 탭에서 '대상(T)' 부분을 수정한다.

 

수정 전 : "C:\Program Files\MySQL\MySQL Server 8.2\bin\mysql.exe" "--defaults-file=C:\Program Files\MySQL\MySQL Server 8.2\my.ini" "-uroot" "-p"

 

수정 후 : "C:\Program Files\MySQL\MySQL Server 8.2\bin\mysql.exe" "--defaults-file=C:\ProgramData\MySQL\MySQL Server 8.2\my.ini" "-uroot" "-p"

 

✏️수정하는 이유 : 아래 캡쳐에 나와있는 것처럼 my.ini 파일은 ProgramData에 있다.

경로가 옳지않아 프로그램이 시작하지 못했던 것 같다.

 

 

✏️ 유즈 케이스란 ?

시스템을 설계하거나 서비스를 설계할 때 전체적인 사용자의 이용 패턴을 분석해 놓은 것

 

✏️ 대표적 도구

lucid chart, draw io(=https://app.diagrams.net/)

 

✏️ draw io (GitHub과 연동하여 사용가능하다.)

✏️ draw io 통해 그린 유즈케이스 예시

 

구성요소 : 시스템(System), 액터(Actor), 유스케이스(Usecase), 관계(Relation)

연관관계 : 실선

포함관계 : 점선 (include, extend로 구분)

 

* include : 로그인 하는 경우 인증이 필요하다. 이런 경우 회원 로그인할 때 인증 유즈케이스가 필요하다고 보고 포함시켜서 실행하기때문에 include로 나타낸다.
extend : 로그인 실패하는 경우 다시 로그인 하는 케이스로 가야하는데 이렇게 특정 조건일 때 실행 되는 유즈 케이스 부분을 확장 관계로 보고 extend로 나타낸다.

<구성요소 예시>
시스템 : DB
* 액터 : 이용자
* 유스케이스 : 회원가입
* 관계 : 실선,점선(포함,연관 관계)

 

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

✏️ 내가 작성한 코드 - BFS

from collections import deque

def chk(word1, word2):
    cnt = 0
    
    for i in range(len(word1)):
        if word1[i] != word2[i]:
            cnt += 1

    if cnt > 1 or cnt == 0:
        return 0
    else:
        return 1


def solution(begin, target, words):
    step = 0
    visit = [False] * len(words)
    q = deque()
    q.append([begin, 0])

    if target not in words:  # target이 words에 없으면 0 리턴
        step = 0
    else:
        while q:
            word, cnt = q.popleft()

            if word == target:
                step = cnt
                break

            for w in range(len(words)):
                if visit[w] == False and chk(words[w], word):
                    visit[w] = True
                    q.append([words[w], cnt + 1])

    return step

 

✏️ 참고

1. 한 번에 한 개의 알파벳만 바꿀 수 있습니다.

위 조건을 참고하여, chk 함수를 작성하였다.

두 단어 각 알파벳을 비교하며 cnt를 증가시키고 cnt가 1인 경우에만 조건에 해당한다.

[ Iterator, Enumeration ]

둘 다 컬렉션 객체들의 요소들을 조회할 때 사용한다.

(for문으로 데이터를 가져오는 방법도 있지만 순환 인터페이스인 iterator와 Enumeration을 사용하는 방법도 있다.)

 

[ Iterator vs Enumeration ]

Iterator는 remove()를 제공한다.

Enumeration보다 Iterator인터페이스를 사용하는 것이 더 낫다.(Enumeration은 legacy)

 

[ Iterator 함수 ]

- hasNext() : 순회할 다음 원소가 남아 있으면 True를 반환한다.

- next() : 다음 원소로 이동하여 반환한다.

- remove() : 가장 최신에 반환 된 원소를 삭제한다.

- forEachRemaining(Consumer<? super E> action) : 모든 원소가 주어진 작업을 처리하거나, 예외가 발생할때까지 작업을 수행한다.

 

[ Enumeration 함수 ]

- asIterator() : Iterator 인터페이스형으로 바꿔서 반환한다.

- hasMoreElements() : enumeration에 순회할 다음 원소가 남아있는지 확인한다. (= Iterator함수 hasNext())

- nextElement() : 다음 원소를 반환한다. (= Iterator함수 next())

 

[ 예제 ]

request.getParameterNames().asIterator().forEachRemaining(...);

request.getParameterNames()의 반환값은 Enumeration이다.

asIterator()을 통해 Enumeration 인터페이스를 Iterator 인터페이스형으로 바꿔서 반환하고,

forEachRemaining()로 예외가 발생하기 전까지 모든 원소에 대해서 주어진 작업을 수행한다.

 

4659번: 비밀번호 발음하기

좋은 패스워드를 만드는것은 어려운 일이다. 대부분의 사용자들은 buddy처럼 발음하기 좋고 기억하기 쉬운 패스워드를 원하나, 이런 패스워드들은 보안의 문제가 발생한다. 어떤 사이트들은 xvtp

www.acmicpc.net

 

✏️ 내가 작성한 코드

vowels = ['a','e','i','o','u']

while(True):

    password = input()
    vowel_num = 0 # 입력받은 문자 모음 개수
    str_list = []  # 0: 모음 , 1: 자음
    break_point = True

    if password == 'end':
        break

    for idx, chr in enumerate(password):
        # 모음 포함 안하면 not
        if chr in vowels:  # 해당 문자가 모음이면
            vowel_num += 1  # 모음개수 추가
            str_list.append(0)  # 모음
        else:
            str_list.append(1)  # 자음

        if idx >= 2:
            if str_list[idx] + str_list[idx - 1] + str_list[idx-2] == 3 or str_list[idx] + str_list[idx - 1] + str_list[idx-2] == 0:
                break_point = False
                print('<{0}> is not acceptable.'.format(password))
                break

        if idx < len(password)-1 and len(password) != 1:
            if chr == password[idx + 1] and chr != 'e' and chr != 'o':  # 연속글자 2번
                break_point = False
                print('<{0}> is not acceptable.'.format(password))
                break

    if vowel_num == 0 and break_point == True:
        print('<{0}> is not acceptable.'.format(password))
    elif vowel_num != 0 and break_point == True :
        print('<{0}> is acceptable.'.format(password))

 

✏️ 참고

break_point 변수 :

자음3개, 모음3개, 같은 글자 연속2번 이 3가지 경우는 입력받은 password의 각 문자들을 다 돌아보기전에 테스트가 확인 가능하여 print할 수 있지만 모음 판단은 위 3개 테스트를 다 통과한 후 모음 개수도 확인하여야 하므로 for문밖에 써줬다.

 

하지만 예를 들어 password가 'tt'라고 입력받았을때,

자음 3개인가(통과) 모음 3개인가(통과), 같은 글자 연속 2번인가(통과 못함) 이렇게 테스트되므로 

for문 안에서 '<tt> is not acceptable' 이 출력되고 break통해 for문 밖으로 나온 다음

밑에 if문에서 vowel_num==0에도 해당하므로 또 한번 더 출력하게 되어 에러가 발생할 것이다.(break_point가 없는 경우)

이를 방지하기 위해 break_point 변수를 두어 for문에서 출력되면 break_point 을 False로 두어 밑에 if에 걸리지 않게 해두었다.

 

1924번: 2007년

첫째 줄에 빈 칸을 사이에 두고 x(1 ≤ x ≤ 12)와 y(1 ≤ y ≤ 31)이 주어진다. 참고로 2007년에는 1, 3, 5, 7, 8, 10, 12월은 31일까지, 4, 6, 9, 11월은 30일까지, 2월은 28일까지 있다.

www.acmicpc.net

 

✏️ 내가 작성한 코드

import sys
x,y = map(int,sys.stdin.readline().strip().split())
mon = [31,28,31,30,31,30,31,31,30,31,30,31] # 1월부터 각 월의 마지막 날짜를 리스트에 담는다.
week = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']
totalDay = 0

for i in range(x-1):
    totalDay += mon[i]

totalDay = totalDay + y
print(week[totalDay%7])

 

✏️ 참고

1월1일은 월요일.

1월2일은 화요일

1월3일은 수요일

...

1월7일은 일요일

x월y일은 ○요일

 

y 나누기 7을 했을 때 나머지 값으로 요일을 알 수 있다.

나머지가 1일때 월요일, 2일때 화요일 , 3일때 수요일 , ..., 0일때 일요일 이다.

1월은 이렇게 나머지로 확인할 수 있다 그렇다면 2월부터는 나머지 값이 달라질텐데 그럼 어떻게 해야할까?

(ex. 2월1일에서 1일이니까 나머지가 1인데 요일은 목요일이다.)

 

요일,날짜는 계속 '이어지는' 존재이므로 '합쳐서' 생각해야한다.

2월1일의 요일을 구해보자.

2월1일은 1월32일과 같다.(32일은 없는 일자지만 이어지는 존재로 생각해본다면..)

32나누기7의 나머지는 4로 목요일인 것을 확인할 수 있다.

 

→ 따라서 x월y일의 요일을 구하려면

(1) x-1월까지의 날짜를 모두 합하고(mon리스트 활용)

(2) 거기에 y일을 더해서 totalDay 변수에 넣고

(3) 나누기 7을 해서 나머지를 구한 다음 week 배열에서 요일을 구하면 된다.

 

2869번: 달팽이는 올라가고 싶다

첫째 줄에 세 정수 A, B, V가 공백으로 구분되어서 주어진다. (1 ≤ B < A ≤ V ≤ 1,000,000,000)

www.acmicpc.net

 

✏️ 내가 작성한 코드 - 1 (시간초과)

# 시간초과 뜸
import sys
a,b,v = map(int,sys.stdin.readline().strip().split())
day = 1
m = 0

while(m != v):
    m += a
    if(m == v):
        break
    m -= b
    day += 1

print(day)

 

✏️ 내가 작성한 코드 - 2

import sys
import math
a,b,v = map(int,sys.stdin.readline().strip().split())

if (v-b)%(a-b) == 0:
    print((v-b)//(a-b))
else:
    print(math.ceil((v-b)/(a-b)))

 

✏️ 참고

* 반복문 사용 시 시간초과 발생.

* 달팽이는 정상에 올라간 후에는 미끄러지지 않는다는 것이 중요하다.

따라서 정상에 도달하는 시점은 이며, (x-1)일동안 (a-b)만큼 오르고 마지막날 낮에 a만큼 올라가서 정상에 도달한다.

이걸 식으로 작성하면 (x-1)(a-b) + a >= v 이며 x >= (v-b)(a-b) 이다.

날짜는 정수여야하므로 math.ceil을 활용하여 올림처리를 한다.

 

+ Recent posts