반응형

여기서 최신버전을 복사해서 pom.xml의 디펜던시에 넣어준다.

 

Maven Repository: org.springdoc » springdoc-openapi-starter-webmvc-ui » 2.5.0 (mvnrepository.com)

<!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui -->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.5.0</version>
</dependency>

 

localhost:8080/swagger-ui/index.html

 

반응형
반응형
import turtle

turtle.title('거북이')
turtle.color('black', 'red')
turtle.shape('turtle')
turtle.penup();
turtle.write("빠른 거북이!!")
turtle.forward(80)
turtle.pendown();
turtle.backward(100)
turtle.exitonclick()

 

 

수행해보니 이번엔 속도가 너무 빠르네요. 속도값은 다음과 같습니다.

 

0: 가장 빠른

1: 가장 느린

3: 느린

6: 보통 (기본값)

10: 빠른

 

지금 기본값이 보통 이라고? 너무 빠른데요. 1로 변경해보겠습니다.

import turtle

turtle.title('거북이')
turtle.color('black', 'red')
turtle.shape('turtle')
turtle.penup();
turtle.write("빠른 거북이!!")

turtle.speed(1) #코드 추가

turtle.forward(80)
turtle.pendown();
turtle.backward(100)
turtle.exitonclick()

 

숫자값이 기억하기 어렵다면 문자로 전달해도 됩니다.

 'fastest', 'fast', 'normal', 'slow', 'slowest'

 

 

반응형
반응형

Tkinter에서 다른 위젯의 배치를 위한 Frame을 사용할 수 있습니다. 아래는 Frame 예제입니다.

import tkinter as tk

root = tk.Tk()
root.title("GUI Frame")
root.geometry("640x480+100+100")
root.resizable(True,True)

frame1 = tk.Frame(root, relief="solid", bd=1, highlightcolor="red")
frame1.pack(side="top", fill="both", expand=True)

frame2 = tk.Frame(root, relief="solid", bd=2, bg="blue")
frame2.pack(side="bottom", fill="both", expand=True)

root.mainloop()

 

 

Frame Parameter

Param 의미 기본값 속성
width 프레임의 너비 0 상수
height 프레임의 높이 0 상수
relief 테두리 모양 flat flat, groove, raised, ridge, solid, sunken
bg 배경색 SystemButtonFace color
bd 테두리 두께 0 상수
padx 내부 x방향 패딩 1 상수
pady 내부 y방향 패딩 1 상수
highlightcolor 프레임이 선택될 때 색상 SystemWindowFrame color

 

반응형
반응형

Tkinter에서 위젯을 화면에 배치하는 방법에는 pack / grid / place의 세가지 방식이 있습니다. grid는 엑셀과 같은 이미지를 떠올리면 될 것 같습니다. 행과 열을 기준으로 위치시키는 방식이고, pack은 상/하/좌/우(동/서/남/북)으로 위치시키는 방식, 그리고 place는 절대좌표계를 이용해서 위치시키는 방식입니다.

 

1. Grid방식

import tkinter as tk

root = tk.Tk()
root.title("GUI Grid위젯배치")
root.geometry("640x480+100+100")
root.resizable(True,True)

bb1 = tk.Button(root, text="(0,0)")
bb1.grid(row=0,column=0)
bb2 = tk.Button(root, text="(0,1)")
bb2.grid(row=0,column=1)
bb3 = tk.Button(root, text="(0,2)")
bb3.grid(row=0,column=2)
bb4 = tk.Button(root, text="(1,0)")
bb4.grid(row=1, columnspan=3, sticky="ew")

root.mainloop()

 

Grid 속성

- 먼저 선언한 Grid부터 배치된다.

- 셀 단위로 배치되며, 한번에 여러 셀을 건너뛰어 배치할 수 없다.

- pack()과 같이 사용할 수 없으며, place()와는 같이 사용할 수 있다.

 

Grid Parameter

Param 의미 기본값 속성
row 행 위치 0  
column 열 위치 0  
rowspan 행 합치기 1  
columnspan 열 합치기 1  
sticky 할당된 공간 내에서 위치 조정. 어디에 고정할 것인가? - n(north), e(east), s(south), w(west)
news와 같이 전방향 고정으로 조합하여 사용 가능
ipadx x방향 내부 패딩 0  
ipady y방향 내부 패딩 0  
padx x방향 외부 패딩 0  
pady y방향 외부 패딩 0  

 

2. Pack방식

Pack은 상하좌우(동서남북) 에 위젯들을 위치시키는 방식입니다.

import tkinter as tk

root = tk.Tk()
root.title("GUI pack 위젯배치")
root.geometry("640x480+100+100")
root.resizable(True,True)

bb1 = tk.Button(root, text="left", width=10)
bb1.pack(side="left", fill="y")
bb2 = tk.Button(root, text="top", width=10)
bb2.pack(side="top")
bb3 = tk.Button(root, text="(right)", width=10)
bb3.pack(side="right")
bb4 = tk.Button(root, text="(bottom)", width=10)
bb4.pack(side="bottom", anchor="n")

root.mainloop()

 

Pack 속성

- 먼저 선언한 pack부터 배치된다.

- pack의 파라미터로 위젯의 크기를 변경할 수 있다.

- grid()와 같이 사용할 수 없으며 place()와는 같이 사용할 수 있다.

 

Pack Parameter

Param 의미 기본값 속성
side 위치(공간)할당 top top, bottom, left, right
anchor 고정 기준 center center, n(north), e(east), s(south), w(west)
news와 같이 전방향 고정으로 조합하여 사용 가능
fill 할당된 공간에 대한 크기 맞춤 none none, x, y, both
expand 미사용 공간 확보 False Boolean
ipadx x방향 내부 패딩 0  
ipady y방향 내부 패딩 0  
padx x방향 외부 패딩 0  
pady y방향 외부 패딩 0  

 

3. place방식

import tkinter as tk

root = tk.Tk()
root.title("GUI Grid위젯배치")
root.geometry("640x480+100+100")
root.resizable(True,True)

bb1 = tk.Button(root, text="(30,30)")
bb1.place(x=30, y=30)
bb2 = tk.Button(root, text="(100,30)")
bb2.place(x=100, y=30)
bb3 = tk.Button(root, text="(30,80)")
bb3.place(x=30, y=80)
bb4 = tk.Button(root, text="(100,80)")
bb4.place(x=100, y=80)

root.mainloop()

 

Place 속성

- 먼저 선언한 요소부터 배치된다.

- place의 절대 위치로 배치되며, 크기를 조정할 수 있다.

- pack(), grid()와 같이 사용할 수 있다.

 

place Parameter

Param 의미 기본값 속성
x x 좌표 0 상수
y y 좌표 0 상수
relx x좌표 배치 비율 0 0~1
rely y좌표 배치 비율 0 0~1
width 위젯 폭 0 상수
height 위젯 높이 0 상수
relwidth 위젯의 상대 너비 0 0~1
relheight 위젯의 상대 높이 0 0~1
anchor 고정 기준 nw n(north), e(east), s(south), w(west)
news와 같이 전방향 고정으로 조합하여 사용 가능

 

 

오늘은 헷갈리지 않도록 grid / pack / place의 속성에 대해 정리하는 시간을 가져봤습니다. 

반응형
반응형

예전에 테스트삼아 해봤는데, 오랫만에 하니까 잘 모르는 것도 있고, 좀 바뀐 부분도 있어서 정리도 할겸 올립니다. 아래와 같은 tkinter 화면을 만들겁니다.

 

1. main.py

우선 main.py에서는 구동만 시켜주고, 화면을 구성하는 파일은 gui.py로 별도 모듈로 만들 예정입니다.

import gui

if __name__ == '__main__':
    gui.main_screen()

 

2. gui.py

import tkinter as tk


def main_screen():
    root = tk.Tk()
    root.title("GUI Sample")
    root.geometry("640x480+100+100")
    root.resizable(True,True)
    root.configure(background='white')  # 배경을 흰색으로 하고,
    # root.wm_attributes("-transparentcolor", 'white') # 흰색을 투명으로 하면 투명한 앱이 됩니다.

    #레이블
    label_1=tk.Label(root, text="위젯 테스트", width=20,height=3,fg="red",relief="solid")
    label_1.pack()
    label_2=tk.Label(root, text="위젯 테스트2", width=20, height=3, fg="blue", relief="groove")
    label_2.pack()

    #리스트박스
    listbox = tk.Listbox(root, selectmode='extended', height=0)
    listbox.insert(0, "no1")
    listbox.insert(1, "no2")
    listbox.insert(2, "no3")
    listbox.insert(3, "no4")
    listbox.insert(4, "no5")
    listbox.pack()

    #체크박스
    checkVal1 = tk.IntVar()
    checkVal2 = tk.IntVar()
    checkBtn1 = tk.Checkbutton(root, text="체크박스 고르기1", variable=checkVal1, activebackground="blue")
    checkBtn2 = tk.Checkbutton(root, text="체크박스 고르기2", variable=checkVal2, activebackground="blue")
    checkBtn1.pack()
    checkBtn2.pack()

    #라디오버튼
    radioVal1=tk.IntVar()
    radioBtn1 = tk.Radiobutton(root, text="1번", value=3, variable=radioVal1)
    radioBtn2 = tk.Radiobutton(root, text="2번", value=6, variable=radioVal1)
    radioBtn3 = tk.Radiobutton(root, text="3번", value=9, variable=radioVal1)
    radioBtn1.pack()
    radioBtn2.pack()
    radioBtn3.pack()

    #상단메뉴
    def close():
        root.quit()
        root.destroy()

    menubar = tk.Menu(root)

    menu_1 = tk.Menu(menubar, tearoff=0)
    menu_1.add_command(label="Sub Menu1-1")
    menu_1.add_command(label="Sub Menu1-2")
    menu_1.add_separator()
    menu_1.add_command(label="종료", command=close)
    menubar.add_cascade(label="Menu1", menu=menu_1)

    menu_2 = tk.Menu(menubar, tearoff=0, selectcolor="red")
    menu_2.add_radiobutton(label="Sub Menu2-1", state="disable")
    menu_2.add_radiobutton(label="Sub Menu2-2")
    menu_2.add_radiobutton(label="Sub Menu2-3")
    menubar.add_cascade(label="Menu2", menu=menu_2)

    menu_3 = tk.Menu(menubar, tearoff=0)
    menu_3.add_checkbutton(label="Sub Menu3-1")
    menu_3.add_checkbutton(label="Sub Menu3-2")
    menu_3.add_checkbutton(label="Sub Menu3-3")
    menubar.add_cascade(label="Menu3", menu=menu_3)

    root.config(menu=menubar)

    # 메뉴 버튼 (상단 메뉴바랑 상관 없음)
    menubutton = tk.Menubutton(root, text="Menu Button", relief="raised", direction="right")
    menubutton.pack()

    menu = tk.Menu(menubutton, tearoff=0)
    menu.add_command(label="Sub-1")
    menu.add_separator()
    menu.add_command(label="Sub-2")
    menu.add_command(label="Sub-3")

    menubutton["menu"] = menu

    # 배치연습
    bb1=tk.Button(root, text="(50,50)")
    bb1.place(x=50,y=50)
    bb2 = tk.Button(root, text="(130,50)",width=10, height=1)
    bb2.place(x=130, y=50)
    bb3 = tk.Button(root, text="(50,100)", border=3)
    bb3.place(x=50, y=100)
    bb4 = tk.Button(root, text="(130,100)")
    bb4.place(x=130, y=100)


    root.mainloop()
반응형
반응형

[ 목차 ]

     

    요즘 하도 개발쪽으로는 관심이 뜸해져서 PC쪽은 쳐다보지도 않은지 꽤 돼었습죠. 그러던 와중에 오랫만에 Manjaro Linux로 부팅을 하고나니 갑자기 예쁜 노트툴이 하나 있으면 하고 생각하게 되었습니다. 그래서 이것 저것 찾아봤는데요 이번에 중점을 둔 것은 무료이면서도, 리눅스 - 모바일 - 웹이 연동이 되느냐는 겁니다. AI 나 여타 블로그로부터 기존의 Evernote, Notion 뿐만아니라 Joplin, CherryTree 등 다양한 추천이 있었습니다. 그 중에 제가 고른 것은 오늘 소개해드릴 Simplenote 와 Notesnook입니다.

     

     

    1. Simplenote (무료 다운로드)

     

    일반적으로 기대하는 깔끔한 디자인의 노트 프로그램입니다. 모바일과 리눅스에서 프로그램을 제공하고 있습니다. 실시간 업데이트가 되어 매우 편리합니다. 체크박스 리스트 형태도 제공하고 태그 기능도 있습니다. 마크다운 문법을 제공하는데, 문서 옵션에서 마크다운에 체크를 해야합니다. 그러나 체크를 한다고 해서 달라지는 건 없고, 마크다운 문법이 그대로 화면에 나타납니다. 단, Publish하면 해당 URL에서 완성된 형태의 문서를 확인할 수 있습니다. 

     

    2. Notesnook (무료 다운로드, 구독 가능)

     

    Notesnook은 프라이버시 보호를 중시하는 노트 앱으로 오픈 소스이며, 모든 데이터는 사용자 기기를 떠나기 전에 종단 간 암호화(end-to-end encryption)되어 데이터의 사생활을 보장합니다. 어느 기기에서든지 장소에 구애받지 않고 메모를 작성하고 관리할 수 있는 크로스플랫폼 앱이에요. Notesnook 은 직관적인 서식 지정 기능을 통해 표제, 글머리 기호 목록, 하이퍼링크가 포함된 구조적인 문서를 만들기 위해 마크다운 구문을 지원합니다. 

     

    Notesnook은 실시간 공유와 협업 기능을 주요 기능으로 제공하며, 사용자가 지정된 개인이나 그룹에게 노트에 대한 액세스 권한을 부여할 수 있습니다. 

    무료와 유료 버전이 있는데 아래와 같은 차이가 있습니다. notebook과 tag를 지원하는 갯수가 우선 차이가 많이 나네요. 그래도 개인적으로는 Evernote 무료가 거의 체험만 할 수 있는 수준인데 비해 notesnook은 우선 노트는 무한대이고 다른 옵션들도 적당히 제공하기에 꽤 괜찮은 조건으로 보입니다.

     

     

    오늘은 이렇게 두가지 리눅스용 노트 프로그램을 알아봤습니다. 리눅스에 여러 노트프로그램이 있지만, 모바일 앱도 제공되는 프로그램이 많진 않은 것 같아요. 그 중에서도 쓸만한 프로그램을 찾은 것 같아 너무 반가웠습니다. 이제 자주 리눅스 들어와서 이것저것 남겨볼까 해요. 그럼 이만~~

    반응형
    반응형

    이번엔 개츠비(Gatsby) 블로그에 Disqus 댓글 기능을 추가해보도록 하겠습니다.

     

    [ 목차 ]

       

      1. Disqus.com에 댓글 추가할 사이트정보 입력

       Disqus.com에 로그인 후 Site Admin 으로 이동하여 기본 정보들을 입력하여 내 사이트를 추가해줍니다. 그리고 설치방법을 찾아보면 Gatsby에 반영하는 방법이 나옵니다. [ Site Admin > 내 사이트 선택 > Installation > Gatsby 선택 ]

       

      Disqus에서는 아래와 같은 형식으로 안내를 합니다. 단 config에서 괄호가 두개 들어가야합니다. 안내와 조금 차이가 있습니다.

      import { Disqus } from 'gatsby-plugin-disqus';
      
      const Template = () => (
          /* Page contents */
      
          <Disqus
              config={{
                  /* Replace PAGE_URL with your post's canonical URL variable */
                  url: 'PAGE_URL',
                  /* Replace PAGE_IDENTIFIER with your page's unique identifier variable */
                  identifier: 'PAGE_IDENTIFIER',
                  /* Replace PAGE_TITLE with the title of the page */
                  title: 'PAGE_TITLE',
              }}
          />
      );

       

       

      2. 플러그인 설치

      이제 내 프로젝트로 와서 아래와 같이 기본적인 플러그인 설치를 진행해줍니다.

      npm install --save gatsby-plugin-disqus

       

      설치된 플러그인은 option과 함께 gatsby-config.js에 추가해줍니다.

      // gatsby-config.js
      module.exports = {
          plugins: [
              {
                  resolve: `gatsby-plugin-disqus`,
                  options: {
                      shortname: `seaofcalm-gatsby`
                  }
              },
          ]
      }

       

      이제 위에서 안내받은 코드를 내 소스에 반영하면 됩니다. 자동으로 md파일들을 HTML로 변환하도록 만든 md-files.js의 소스코드를 아래와 같이 수정했습니다. GraphQL에서 필요한 데이터도 잊지않고 가져와줘야 합니다.

      import React from "react"
      import { graphql } from "gatsby"
      import { GatsbyImage, getImage } from "gatsby-plugin-image"
      import Layout from "../components/layout"
      import { Disqus } from "gatsby-plugin-disqus"
      
      export default function Template({ data }) {
        
        const { markdownRemark } = data
        const { frontmatter, html } = markdownRemark
        const thumbnailImg = getImage(frontmatter.thumbnail?.childImageSharp?.gatsbyImageData)
      
        return (
          <Layout>
            <div className="blog-post-container">
              <div className="blog-post">
                {/* <GatsbyImage 
                  image={thumbnailImg} 
                  alt="Thumbnail" 
                  imgStyle={{ objectFit: "cover", objectPosition: "50% 50%" }}
                  style={{ width: "100%`" }}
                /> */}
                <h1>{frontmatter.title}</h1>
                <h2>{frontmatter.date}</h2>
                <div dangerouslySetInnerHTML={{ __html: html }} />                   
              </div>
            </div>
            <Disqus
              config={{
                /* Replace PAGE_URL with your post's canonical URL variable */
                url: `${data.site.siteMetadata.siteUrl + frontmatter.slug}`,
                /* Replace PAGE_IDENTIFIER with your page's unique identifier variable */
                identifier: `${markdownRemark.id}`,
                /* Replace PAGE_TITLE with the title of the page */
                title: `${frontmatter.title}`,
              }}
            /> 
          </Layout>
        )
      }
      
      export const query = graphql`
        query($slug: String!) {
          markdownRemark(fields: { slug: { eq: $slug } }) {
            html
            id
            frontmatter {
              date(formatString: "MMMM DD, YYYY")        
              title  
              slug
              thumbnail {
                childImageSharp {
                  gatsbyImageData
                }
              }
            }
          }
          site {
            siteMetadata {
              siteUrl
            }
          }
        }
      `

       

      <결과>

      localhost:8000에서도 잘 확인이 됩니다.

       

      반응형
      반응형

      [ 목차 ]

        구글 서치콘설에 등록하기 위해서는 3단계를 거쳐야 합니다. 

        1. sitemap.xml 

        2. robots.txt

        3. Google Search Console 등록

         

        1. Sitemap.xml 생성

        가장 먼저 sitemap.xml을 생성합니다. 생성 방법은 플러그인 추가로 쉽게 진행할 수 있습니다. gatsby-plugin-sitemap, gatsby-plugin-advanced-sitemap 플러그인을 추가해줍니다.

        npm i gatsby-plugin-sitemap
        
        // gatsby가 버전 5로 올라가면서 아래의 플러그인은 아직 설치가 안되고 있습니다.
        npm i gatsby-plugin-advanced-sitemap

        gatsby-config.js 에 플러그인을 추가해줍니다.

        module.exports = {
        	siteMetadata:{
            	siteUrl: 'https://......com/',
            },
            plugins: [
               ...
               'gatsby-plugin-sitemap'
               ...
           ],
        };

        build후 URL/sitemap-index.xml에 접속하면 sitemap을 확인할 수 있습니다.

         

        2. Robots.txt 생성

        robots.txt는 웹페이지 크롤링 봇들이 내 사이트를 크롤링을 할 때 어떤 부분을 허용하고, 어떤 부분을 제한할지 설정하는 파일입니다. 이 역시 gatsby-plugin-robots-txt 플러그인 추가로 간단히 해결할 수 있습니다.

        npm i gatsby-plugin-robots-txt

        gatsby-config.js 에 플러그인을 추가하고 설정해줍니다.

        module.exports = {
        	siteMetadata:{
            	siteUrl: 'https://......com/',
            },
            plugins: [
               ...
               'gatsby-plugin-sitemap',
               ...
               {
               	resolve: 'gatsby-plugin-robots-txt',
                options: {
                	host:'https://{my URL}.com/',
                    sitemap: 'https://{my URL}.com/sitemap-index.xml',
                    policy:[{ userAgent: '*', allow: '/'}],
                },
               },
               ...
           ],
        };

         

        3. Google Search Console 등록

        서치 콘솔에서 새로운 사이트를 등록하는 방법은 [ 여기 ]포스팅을 참조하시기 바랍니다. 이제 <meta>태그를 적용시켜줘야하는데, 기본 Gatsby Starter로 시작했다면, src/components/layout.js파일을 수정하는게 편합니다. 우선 react-helmet이라는 플러그인을 설치해줍니다.

        npm i react-helmet

        그리고 아래와 같이 <Header /> 태그의 아래쪽에 <Helmet> 컴포넌트를 이용해서 코드를 추가해줍니다

        import { Helmet } from "react-helmet"
        
        // ...
        
        return (
            <>
              <Header siteTitle={data.site.siteMetadata?.title || `Title`} />
              
              <Helmet>        
                <meta name="google-site-verification" content="{your google code}" />
              </Helmet>
              <div
                style={{
                  margin: `0 auto`,
                  maxWidth: `var(--size-content)`,
                  padding: `var(--size-gutter)`,   
                  
                }}
              >
          // ...

         

        정상 적용되면 구글 서치콘솔에서 "확인" 등 다음단계 진행 시 소유권이 확인됩니다. 

        (ps) 이 방법으로 적용이 안될 경우 seo.js파일에 직접 넣어주는 방법으로도 가능합니다.

        return (
            <>
              <title>{defaultTitle ? `${title} | ${defaultTitle}` : title}</title>
              <meta name="description" content={metaDescription} />
              <meta property="og:title" content={title} />
              <meta property="og:description" content={metaDescription} />
              <meta property="og:type" content="website" />
              <meta name="twitter:card" content="summary" />
              <meta name="twitter:creator" content={site.siteMetadata?.author || ``} />
              <meta name="twitter:title" content={title} />
              <meta name="twitter:description" content={metaDescription} />
              <meta
                key="google-site-verification"
                name="google-site-verification"
                content="인증코드" // 여기 추가
              />
              {children}
            </>
          )

         

        다음으로는 서치콘솔 화면에서 sitemap.xml을 인식시켜줍니다.

        반응형

        + Recent posts