해당 내용은 스프링 부트와 AWS로 혼자 구현하는 웹서비스 책 내용을 복습한 내용입니다.

 

API를 만들기 위해 총 3개의 클래스가 필요합니다.

* Request 데이터를 받을 Dto

* API 요청을 받을 Controller

* 트랜잭션, 도메인 기능 간의 순서를 보장하는 Service

tip ) service는 비지니스 로직을 처리하지 않습니다. 그 역할은 Domain이 실행합니다.

 

* Web Layer

  * 흔히 사용하는 컨트롤러(@Controller)와 JSP/Freemaker 등의 뷰 템플릿 영역입니다.

  * 이외에도 필터(@Filter), 인터셉터, 컨트롤러 어드바이스(@ControllerAdvice) 등 외부 요청과 응답에 대한 전반적인 영역을 이야기합니다.

 

* Service Layer

  * @Service에 사용되는 서비스 영역입니다.

  * 일반적으로 Controller와 Dao의 중간 영역에서 사용됩니다.

  * @Transactional이 사용되어야 하는 영역이기도 합니다.

 

* Repository Layer

  * Database와 같이 데이터 저장소에 접근하는 영역입니다.

  * 기존에 개발하셨던 분들이라면 Dao(Data Access Object) 영역으로 이해하시면 쉬울것입니다.

 

* Dtos

  * Dto(Data Transfer Object)는 계층간 데이터를 교환하기 위한 객체를 이야기하며 Dtos는 이들의 영역을 얘기합니다.

  * 예를 들어 뷰 템플릿 엔진에서 사용될 객체나 Repository Layer에서 결과로 넘겨준 객체 등이 이들을 이야기합니다.

 

* Domain Model

  * 도메인이라 불리는 개발 대상을 모든 사람이 동일한 관점에서 이해할 수 있고 공유할 수 있도록 단순화시킨 것을 도      메인 모델이라고 합니다.

 

  * 이를테면 택시 앱이라고 하면 배차, 탑승, 요금 등이 모두 도메인이 될 수 있습니다.

  * @Entity를 사용해보신 분들은 @Entity가 사용된 영역 역시 도메인 모델이라고 이해 해주시면 됩니다.

  * 다만, 무조건 데이터베이스의 테이블과 관계가 있어야만 하는 것은 아닙니다.

  * VO처럼 값 객체들도 이 영역에 해당하기 떄문입니다.

 

 

 

'스프링' 카테고리의 다른 글

@Entity  (0) 2022.02.01
spring boot 에서 google login을 사용해보았다.  (0) 2021.12.18
스프링 서버 단에서 데이터 처리하는 방식  (0) 2021.11.27
Auditing @CreatedDate @LastModifiedDate  (0) 2021.11.27
h2 console  (0) 2021.11.27

 

url이 달라서 발생한 오류였다.

오늘은 이것이 코딩테스트에서 미로 탈출 문제를 풀어보았다.

# This is a sample Python script.

# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.

from collections import deque

# Press the green button in the gutter to run the script.
if __name__ == '__main__':
    # N, M을 공백으로 구분하여 입력받기
    n, m = map(int, input().split())
    # 2차원 리스트의 맵 정보 입력받기
    graph = []
    for i in range(n):
        graph.append(list(map(int ,input())))

    # 이동할 네 방향 정의(상, 하, 좌, 우)
    dx = [-1, 1, 0, 0]
    dy = [0, 0, -1, 1]

    # BFS 소스코드 구현
    def bfs(x, y):
        # 큐(Queue) 구현을 위해 deque 라이브러리 사용
        queue = deque()
        queue.append((x,y))
        # 큐가 빌 때까지 반복
        while queue:
            x, y = queue.popleft()
            # 현재 위치에서 네 방향으로의 위치 확인
            for i in range(4):
                nx = x + dx[i]
                ny = y + dy[i]
                # 미로 찾기 공간을 벗어난 경우 무시
                if nx < 0 or ny < 0 or nx >= n or ny >= m:
                    continue
                # 벽인 경우 무시
                if graph[nx][ny] == 0:
                    continue
                # 해당 노드를 처음 방문하는 경우에만 최단 거리 기록
                if graph[nx][ny] == 1:
                    graph[nx][ny] = graph[x][y] + 1
                    queue.append((nx,ny))
            # 가장 오른쪽 아래까지의 최단 거리 반환
        return graph[n - 1][m - 1]
        # BFS를 수행한 결과 출력
    print(bfs(0, 0))

해당 문제를 풀다가 pycharm을 깔고 실행해보기위해서 깔고 reboot를 실행했는데 이전에

pythontutor에서 풀던 문제를 날려버리는 바람에 나의 답안은 버리게 되었다. 하지만 해당 방식은 dfs 방식이였기 때문에 위 방식이 답안이기 때문에 올바른 방식이다. 위 방식으로 한번 풀어보니 놀랍도록 멋진 코드인거 같다. 

n, m = map(int, input().split())

ice =   [[0]*m for _ in range(n)]
visit = [[0]*m for _ in range(n)]
result = 0


def dfs(x, y):
    dirs = [(-1,0), (0, -1), (1, 0), (0, 1)]
    
    visit[y][x] = 1
    
    for dir in dirs:
        xd = x + dir[0]
        yd = y + dir[1]
        if xd>=0 and xd<m and yd >=0 and yd <n:
            if visit[yd][xd] == 0 and ice[yd][xd] == 0:
                dfs(xd, yd)

for i in range(n):
    str1 = input()
    for j in range(len(str1)):
        ice[i][j] = int(str1[j])

for i in range(n):
    for j in range(m):
        if ice[i][j] == 0 and visit[i][j] == 0:
            result += 1
            dfs(j, i)
            
print(result)

'Today I Learned' 카테고리의 다른 글

KendoGrid empty  (0) 2021.12.15
kendogrid batch  (0) 2021.12.14
kendogrid-isNew()  (0) 2021.12.09
이것이 코딩테스트이다 - 게임 개발  (0) 2021.12.08
깃 크라켓 사용해보기  (0) 2021.12.05

오늘은 테이블에 행을 추가 하는 것이 아니라면 아이디를 수정하지 못하게 막는 기능을 찾아봤습니다. 

일반적으로 특정 속성을 편집하지 못하게 막는 것은 간단하게 할 수 있지만 특정 상태에서는 가능하게 특정 상태에서는 불가능하게 하는 것은 조금 복잡한 문제였습니다. 인터넷을 잘 찾아보니 isNew()라는 함수가 눈에 띄었습니다. isNew는 테이블의 행의 상태가 create인지 edit인지 구별할 수 있는 기능을 제공합니다. 따라서 해당 함수를 사용해서 평소에는 ID 값을 편집하지 못하게 막고 행을 추가할 때만 아이디 값을 수정할 수 있게끔 했습니다.

 

isNew를 사용한 코드

edit function (e) { 
            console.log(EDIT, e.model, e.model.isNew(), e.model.id, e.model._defaultId);
            if (!e.model.isNew()) {
                if (e.container.find("input").attr("name") == "GROUPID") {
                    this.closeCell();
                }
          
        }

 

'Today I Learned' 카테고리의 다른 글

kendogrid batch  (0) 2021.12.14
음료수 얼려먹기 나의 답안  (0) 2021.12.09
이것이 코딩테스트이다 - 게임 개발  (0) 2021.12.08
깃 크라켓 사용해보기  (0) 2021.12.05
TIL JUNIT, MOCKITO  (0) 2021.12.01

https://stackoverflow.com/questions/63521181/java-file-outside-of-source-root-intellij

 

Java file outside of source root intelliJ

I have cloned a spring boot project from GitLab having multiple branches in IntelliJ. I checkout to the branch in which I want to work. But I am getting "Java file outside of source root"...

stackoverflow.com

해당 오류는 file > project structure > modules에서 파일 경로를 java 파일로 resources를 덮어쓰면 해결된다.

오늘아래와 같은 방식으로 문제를 해결하였다. 하나의 테스트케이스만으로 검증하여서 진짜 맞는 코드인지 분간하기가 어렵다. 

내가 푼 풀이

n, m = map(int, input().split())
x, y, dir = map(int, input().split())

visited = [[0]*m for _ in range(n)]
field1 = [[0]*m for _ in range(n)]
dirs = [(0, -1), (1, 0), (0, 1), (-1, 0)]
result = 1
visited[y][x] = 1

for i in range(n):
    list1 = list(map(int, input().split()))
    for j in range(len(list1)):
        if list1[j] == 1:
            field1[i][j] = 1
            
def dfs(x, y, d,time):
    global result
    d -= 1
    if d <0:
        d = 3
        
    xd = x + dirs[d][0]
    yd = y + dirs[d][1]
    
    if xd>=0 and xd <m and yd>=0 and yd<n:
        if visited[yd][xd] != 1 and field1[yd][xd] !=1:
            result +=1
            visited[yd][xd] = 1
            time = 0
            dfs(xd, yd, d, time)
        else : 
            if time >= 4:
                return
            else:
                dfs(x, y,d, time +1)        
    else:
        
        if time >= 4:
            return
        else:
            dfs(x, y,d, time +1)   
            
dfs(x, y, dir, 0)

정답

n , m = map(int, input().split())

d = [[0] * m for _ in range(n)]
x, y, direction = map(int, input().split())
d[x][y] = 1

array = []
for i in range(n):
    array.append(list(map(int, input().split())))
    
dx = [-1, 0, 1, 0]
dy = [0, 1, 0 ,-1]

def turn_left():
    global direction
    direction -= 1
    if direction == -1:
        direction = 3
        
count = 1
turn_time = 0
while True:
    turn_left()
    nx = x + dx[direction]
    ny = y + dy[direction]
    if d[nx][ny] == 0 and array[nx][ny] == 0:
        d[nx][ny] = 1
        x = nx
        y = ny
        count += 1
        turn_time = 0
        continue 
    else:
        turn_time += 1
    if turn_time == 4:
        nx = x - dx[direction]
        ny = y - dy[direction]
        if array[nx][ny] == 0:
            x = nx
            y = ny
        else:
            break
        turn_time = 0
print(count)

'Today I Learned' 카테고리의 다른 글

kendogrid batch  (0) 2021.12.14
음료수 얼려먹기 나의 답안  (0) 2021.12.09
kendogrid-isNew()  (0) 2021.12.09
깃 크라켓 사용해보기  (0) 2021.12.05
TIL JUNIT, MOCKITO  (0) 2021.12.01

https://en.wikipedia.org/wiki/Dapper_ORM

 

Dapper ORM - Wikipedia

 

en.wikipedia.org

Dapper는 .NET 프레임워크를 위한 마이크로소프트의 ORM(Object-Relational Mapping)  제품이다. 

 

그렇다면, ORM(Object-Relational Mapping)이란 무엇인가 ? 

이름 뜻을 보면서 유추해보면 관계되는 객체를 매핑해주는 제품인거 같다.

위키페디아에 따르면 객체 지향 프로그래밍 언어를 사용하여 호환되지 않는 유형 시스템 간에 데이터를 변환하는 프로그래밍 기법이다. 이것은 사실상 프로그래밍 언어 내에서 사용될 수 있는 가상 객체 데이터베이스를 만든다라고 한다.

좀더 쉽게 이해해보기 위해서 youtube 강의를 시청했다. 

https://www.youtube.com/watch?v=4CRpndN3tP0 

해당 강의를 통해 이해한걸 정리해보면, 객체지향 프로그래밍 언어에서 사용하는 데이터 타입과 데이터베이스에서 사용하는 데이터 타입은 매칭되지 않는다. 그렇기 때문에 데이터베이스에 데이터를 요청하거나 보낼 때 데이터 타입 변환을 해줘야 하는데 이러한 작업은 매우 귀찮은 작업이고 시간이 많이 들어간다 따라서 데이터베이스에서 받은 데이터 타입을 객체지향 언어에서 이해할 수 있는 데이터 타입으로 변환해주는 것이 orm의 역할이라 볼 수 있다.

 

데퍼를 사용함으로써 얻을 수 있는 이점을 몇가지 알아보면서 마무리 하겠다.

데퍼를 사용하는 이유중 주요한 이유는 빠르다는 것이다. 현재 재직중인 회사에서도 Entity Framework에서 Dapper로 변경을 하였는데 이유는 데이터를 조회시 한번에 가져와야되는 데이터의 수가 증가함에 따라 속도가 느려저서 속도를 개선할 필요성이 필요해서였다. 

그리고 코드 라인 수가 감소한다는 이점도 있는Dapper에게 단순히 파라미터와 쿼리문만 주면 되기 때문으로 보인다. 

 

 

해당 문제를 해커랭크에서 풀어보았습니다. 해당 문제는 해쉬로 푸는 문제지만 이번 문제의 경우 집합이 유리해보여서 set을 사용하였습니다. 

 

해당 문제의 코드는 아래와 같습니다.

def twoStrings(s1, s2):
    # Write your code here
    s1_set = set()
    isSub = False
    answer = 'NO'
    for str1 in s1:
        s1_set.add(str1)
    for str2 in s2:
        if str2 in s1_set:
            answer = 'YES'
            break
    return answer

해당문제를 풀면서 긴가민가 했던 부분이 있는데 스트링을 포문으로 그냥 range를 안쓰고 문자열로만으로 가능할지 의문이였는데 시도해보니 잘되는 것을 확인할 수 있었습니다.

'알고리즘' 카테고리의 다른 글

큰 수의 법칙 그리디  (0) 2021.12.14
미로 탈출 - bfs  (0) 2021.12.13
BFS 1325번 효율적인 해킹  (0) 2021.12.01
백준 1012번 유기농 배추  (0) 2021.11.30
기본 DFS와 BFS  (0) 2021.11.24

월래 Todya I Learned는 꾸준하게 하루마다 작성해야 하지만 쉽지 않군요 그래서 이번주에 배운 내용 중 생각나고 중요한 내용 위주로 간략하게 적어보겠습니다. 

 

이번주는 스프링에대해 공부를 해봤습니다. 스프링 데이터 코드를 단순하게 깃과 연동해서 올려왔었지만 이번에는 특별하게 깃 크라켄이란 것을 사용해보았습니다.

 

GitKraken

https://www.gitkraken.com/

 

Free Git GUI for Windows, Mac, Linux | GitKraken

Unleash GitKraken, the free Git GUI for Windows, Mac & Linux! This intuitive Git GUI simplifies and streamlines Git processes.

www.gitkraken.com

깃크라켄은 GUI 환경에서 깃을 다를 수 있는 툴입니다. 

 

 

우선 깃 크라켄을 이용하기 위해서 Repository를 하나 만듭니다.

Repository를 다 만든었으면 깃크라켄을 열어 Clone a repo를 클릭합니다.

그럼 (클론>GitHub.com) 으로가서 Repository to clone에서 아까 만든 Repository의 이름을 입력하면 검색이 되는데 클릭합니다.

Clone the repo! 버튼을 클릭하면 아래와 같이 깃크라켄이 첫 커밋을 하겠다는 메시지가 나타나면 Initialize 버튼을 클릭합니다.

 

버튼을 클릭하였다면 아래와 같은 화면을 볼 수 있습니다.

해당 화면에서는 Push하기전에 커밋햇던 내용을 Undo로 취소하거나 커밋한 내요을 Push하는 등의 기능을 사용해 보았습니다.

 

화면을 보면 Branch는 master이고 아까 깃 크라켄에게 부탁한 Initial commit이 된 것을 확인할 수 있습니다.

 

우측에는 커밋할 당시 생성된 커밋 메시지를 확인할 수 있고 수정할 수도 있습니다.

 

그러면 File > Preferences... 로 넘어가 봅시다.

아래 화면으로 넘어가면 Gitflow를 선택하고 Develop에서 develop 그리고 Initialize Gitflow를 누릅니다.

https://gist.github.com/ihoneymon/a28138ee5309c73e94f9

 

git 을 기반으로 git-flow를 사용하여 애플리케이션 배포버전을 관리하자.

git 을 기반으로 git-flow를 사용하여 애플리케이션 배포버전을 관리하자. GitHub Gist: instantly share code, notes, and snippets.

gist.github.com

위와 같이 진행하고 있는 작업은 브랜치를 새로 만드는 것입니다. develop 브랜치를 따로 만들어 사용하는 이유는 아직 변경사항 개발이 완료되지는 않았지만 커밋하여 구성원과 코드 공유를 하기 위해서입니다. master 브랜치는 실제로 배포가 준비된 코드만 올라가야되기 때문에 master 브랜치로 현재 개발중인 코드를 커밋하지 않습니다. develop 브랜치를 완성하였으면 master 브랜치와 병합을 하여 master 브랜치에 develop 브랜치를 반영하여 줍니다.

 

다시 본화면으로 돌아오면 develop 브랜치가 생성된 것을 확인할 수 있습니다. 그럼 develop 브랜치를 더블클릭하면 develop 브랜치로 넘어가서 작업할 수 있습니다.

이제 코드 작업을 한 뒤 깃 크라켄으로 돌아오면

아래와 같이 되는데 우측에서 원하는 파일들만 골라서 커밋을 따로따로 진행할 수도 있습니다.

커밋을 완료하였다면 push를 통해 깃허브에 반영할 수 있습니다.  push는 되도록이면 모든 커밋을 한다음 마지막에 하는 것이 좋은데 가끔 실수하여 커밋을 되돌려야 할 때가 있습니다. 그때 push가 되지 않은 상황이라면 undo 기능을 통해 되돌릴 수 있습니다.

 

이제 developer 브랜치에서 개발이 완료되었으면 master 브랜치와 병합해주도록 합시다.

merge 방법은 

https://www.youtube.com/watch?v=mS8oUqqc2G8 

아래 영상을 참조해주세요

 

'Today I Learned' 카테고리의 다른 글

kendogrid batch  (0) 2021.12.14
음료수 얼려먹기 나의 답안  (0) 2021.12.09
kendogrid-isNew()  (0) 2021.12.09
이것이 코딩테스트이다 - 게임 개발  (0) 2021.12.08
TIL JUNIT, MOCKITO  (0) 2021.12.01

+ Recent posts