728x90
반응형

TIL (Today I Learned)

2022.02.28

오늘 읽은 범위

5장 형식 맞추기

책에서 기억하고 싶은 내용을 써보세요.

  • 맨 처음 잡아놓은 구현 스타일과 가독성 수준은 유지보수 용이성과 확장성에 계속 영향을 미친다 (p.96)
  • 신문 기사처럼 작성하라(고차원 개념과 알고리즘에서 저차원 함수와 세부 내역 순서로 묘사하자) (p.97)
  • 줄 바꿈이 개념을 분리한다면 세로 밀집도는 연관성을 의미함 -> 밀접한 코드는 세로로 가까이 놓여야 함 (p.100)
  • 변수는 사용하는 위치에 최대한 가까이 선언, 인스턴스 변수는 클래스 맨 처음에 선언 (p.101, 103)
  • 한 함수가 다른 함수를 호출한다면 두 함수는 세로로 가까이 배치 -> 가능하면 호출하는 함수를 위로 배치 (p.103)
  • 개념적인 친화도가 높을수록 코드를 가까이 배치한다 (p.106)
  • 코드 스타일은 일관적이고 매끄러워야 한다. 한 소스 파일에서 봤던 형식이 다른 소스 파일에도 쓰이리라는 신뢰감을 독자에게 줘야 한다 (p.114)

 

오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요

5장은 코드 형식에 대한 이야기를 하고 있다. 전에 42 Seoul에 참여할 때 코드 형식 때문에 고민했던 일이 기억나서 

그런지 되게 재미있게 읽었다. 제일 기억에 남는 말은 신문 기사처럼 작성하라이다. 아래로 내려갈수록 의도를 세세하게

묘사하라는 의미인데, 어떤 느낌인지 확 이해가 돼서 그런지 기억에서 잊혀지 것 같지가 않다.   

728x90
반응형

'책 리뷰 > 클린코드' 카테고리의 다른 글

7장 오류 처리  (0) 2022.03.04
6장 객체와 자료구조  (0) 2022.03.01
4장 주석  (0) 2022.02.27
3장 함수  (0) 2022.02.22
2장 의미 있는 이름  (0) 2022.02.20
728x90
반응형

TIL (Today I Learned)

2022.02.27

오늘 읽은 범위

4장 주석

책에서 기억하고 싶은 내용을 써보세요.

  • 코드만이 자기가 하는 일을 진실되게 말한다 (p.69)
  • 주석은 나쁜 코드를 보완하지 못한다 -> 주석을 가능한 줄이도록 꾸준히 노력해야 한다 (p.69)
  • 코드로 의도를 표현하라 (p.70)
  • 이해가 안 되어 다른 모듈까지 뒤져야 하는 주석은 독자와 제대로 소통하지 못하는 주석이다 (p.76)
  • 주석으로 처리한 코드는 밉상이다 -> 웬만하면 지우자 (p.86)

 

오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요

4장은 주석을 만약 쓰게 된다면 이런 경우에 사용하자라는 내용을 담고 있다. 법적 정보, 기본적 정보 제공, 의도 설명, 

경고, TODO, 강조 등등이 좋은 주석이고 나머지는 안 좋은 주석이다. 이런 것들은 코드에 대한 설명보다는 정보를 

제공하는 것이라 꼭 필요한 것 같다. 

제일 인상 깊었던 말은 주석은 나쁜 코드를 보완하지 못한다이다. 항상 정보를 제공하기 위한 주석보다는 내 코드에

대한 부연설명을 하기 위해 주석을 많이 썼던 것 같은데, 앞으로는 의식하면서 주석을 줄여나가야겠다.

이 책을 안 읽었으면 이런 생각을 못했을 것 같기에 읽기 잘했다는 생각이 들었다! 

728x90
반응형

'책 리뷰 > 클린코드' 카테고리의 다른 글

6장 객체와 자료구조  (0) 2022.03.01
5장 형식 맞추기  (0) 2022.03.01
3장 함수  (0) 2022.02.22
2장 의미 있는 이름  (0) 2022.02.20
1장 깨끗한 코드  (0) 2022.02.20
728x90
반응형

처음에는 아래와 같이 첫날부터 확인하는 방식으로 풀었다. 

N = int(input())
li = [list(map(int, input().split())) for _ in range(N)]
dp = [0 for _ in range(N+1)]

for i in range(N):
    for j in range(i + li[i][0], N+1):
        if dp[j] < dp[i] + li[i][1]:
            dp[j] = dp[i] + li[i][1]

print(dp[-1])

통과되긴 해도 일단 반복문이 2개라 아래 사진과 같이 무의미한 동작이 상당히 많다.

반복문 하나로 끝낼 방법이 없을까 하다가 그냥 마지막 날부터 확인하면 되겠다는 생각이 들어 아래와 같이 수정했다.

N = int(input())
li = [list(map(int, input().split())) for _ in range(N)]
dp = [0 for _ in range(N+1)]

for i in range(N-1, -1, -1):
    if i + li[i][0] > N:
        dp[i] = dp[i+1]
    else:
        dp[i] = max(dp[i+1], li[i][1] + dp[i + li[i][0]])
    
print(dp[0])
728x90
반응형
728x90
반응형

TIL (Today I Learned)

2022.02.22

오늘 읽은 범위

3장 함수

 

책에서 기억하고 싶은 내용을 써보세요.

  • 작게 만들어라! -> 중첩 구조가 생길 만큼 함수가 커져서는 안 된다 (p.42, 44)
  • 함수는 한 가지를 해야 한다. 그 한 가지를 잘해야 한다. 그 한 가지만을 해야 한다 (p.44)
  • 함수당 추상화 수준은 하나로! -> 일련의 TO 문단을 읽듯이 프로그램이 읽혀야 한다 (p.45, 46)
  • 서술적인 이름을 사용하라! (p.49)
  • 함수 인수 -> 인수는 개념을 이해하기 어렵게 만든다 -> 3개 이상부터는 좀... 그렇다 (p.50)
  • 명령과 조회를 분리하라! (p.56)
  • 오류 코드보다 예외를 사용하라! -> try / catch 블록을 별도 함수로 뽑아내는 편이 좋다. (p.57, 58)
  • 반복하지 마라! -> 중복은 소프트웨어에서 모든 악의 근원이다. 많은 원칙과 기법이 중복을 없애거나 제어할 목적으로 나왔다 (p.60)

 

오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요

제일 인상 깊었던 글은 반복하지 마라이다. 앞에서 나온 작게 만들어라, 한 가지만 잘 돌아가게 해라, 추상화 수준을

하나로 해라 등등이 다 포함하는 내용이라고 생각하기 때문이다. 그리고 인수 관련된 내용도 참 좋았는데 평소에

함수에 인수를 3, 4개씩 박았던 기억이 있어서 앞으로는 주의해야겠다는 생각이 들었다.

 
728x90
반응형

'책 리뷰 > 클린코드' 카테고리의 다른 글

5장 형식 맞추기  (0) 2022.03.01
4장 주석  (0) 2022.02.27
2장 의미 있는 이름  (0) 2022.02.20
1장 깨끗한 코드  (0) 2022.02.20
노마드 코더 클린코드 시작  (0) 2022.02.18
728x90
반응형

TIL (Today I Learned)

2022.02.20

오늘 읽은 범위

2장 의미 있는 이름 

 

책에서 기억하고 싶은 내용을 써보세요.

  • 의도를 분명히 밝혀라 -> 따로 주석이 필요하다면 의도를 분명히 드러내지 못했다는 말이다 (p.22)
  • 그릇된 정보를 피하라 -> 일관성이 떨어지는 표기법은 그릇된 정보다 (p.24, 25)
  • 의미 있게 구분하라 -> 읽는 사람이 차이를 알도록 이름을 지어라 (p.25, 27)
  • 검색하기 쉬운 이름을 사용하라, 긴 이름이 짧은 이름보다, 검색하기 쉬운 이름이 상수보다 좋다 (p.28)
  • 단 이름 길이는 범위 크기에 비례해야 한다 (p.28)
  • 클래스 이름 -> 명사, 명사구(Customer, Account), 메서드 이름 -> 동사, 동사구(postPayment, deletePage) (p.32)
  • 한 개념에 한 단어를 사용하라 -> 메서드 이름은 독자적이고 일관적이어야 한다 (p.33)
  • 의미 있는 맥락을 추가하라 -> 맥락만 개선해도 함수 쪼개기가 쉬워지고 알고리즘도 좀 더 명확해진다 (p.35)

 

오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요

변수나 함수, 클래스의 이름을 고민하는 것은 코딩 공부를 해본 사람이라면 모두가 공감할 내용인 것 같다.

나는 그럴 때마다 깊게 고민하지 않고 당장 납득이 가는 이름? 정도로 타협해서 구현만 했었던 것 같다.

이렇게 짠 코드는 시간이 지나고 봤을 때 정확하게 무슨 동작을 하는 코드였는지 기억이 안나는 경우가 대부분이었다. 

내 코드도 다시 해석해야 되는데 다른 사람이 보기에는 얼마나 답답했을까라는 생각이 처음으로 들었다.

오늘 제일 기억에 남는 글은 의도를 분명히 밝혀라이다. 생각해보면 함수나 클래스의 의도가 확실하지 않을수록 내

주석이 길어졌던 것 같다. 주석이 필요 없는 코드가 1장에서 말했던 아름다운, 읽는 재미가 있는 코드가 아닐까 싶다!  

728x90
반응형

'책 리뷰 > 클린코드' 카테고리의 다른 글

5장 형식 맞추기  (0) 2022.03.01
4장 주석  (0) 2022.02.27
3장 함수  (0) 2022.02.22
1장 깨끗한 코드  (0) 2022.02.20
노마드 코더 클린코드 시작  (0) 2022.02.18
728x90
반응형

TIL (Today I Learned)

2022.02.19

오늘 읽은 범위

1장 깨끗한 코드 

 

책에서 기억하고 싶은 내용을 써보세요.

  • 깨끗한 코드는 ‘보기에 즐거운’ 코드다. (p.9)
  • 깨끗한 코드는 잘 쓴 문장처럼 읽힌다. 깨끗한 코드는 결코 설계자의 의도를 숨기지 않는다. (p.10)
  • 깨끗한 코드는 작성자가 아닌 사람도 읽기 쉽고 고치기 쉽다. (p.11)
  • 깨끗한 코드는 주의 깊게 작성한 코드다. (p.12)
  • 중복을 피하라. 한 기능만 수행하라. 제대로 표현하라. 작게 추상화하라. (p.14)
  • 새 코드를 짜면서 우리는 끊임없이 기존 코드를 읽는다. 비율이 이렇게 높으므로 읽기 쉬운 코드가 매우 중요하다. (p.18)
  • 보이스카우트 규칙: 캠핑장은 처음 왔을 때보다 더 깨끗하게 해놓고 떠나라. (p.19)

 

오늘 읽은 소감은? 떠오르는 생각을 가볍게 적어보세요

말그대로 클린코드, 깨끗한 코드란 무엇일까에 대해 설명하는 챕터이다. 제일 와닿았던 설명은 "깨끗한 코드는 보기에 즐겁고, 잘 쓴

문장처럼 읽힌다" 였던 것 같다. 평소에 코드를 짤 때 구현만 하고 리팩토링을 안 해본 나로선 배울 수 있는 것이 엄청 많을 책인 것 같고, 

나중에 직장 동료들이 내 코드를 봤을 때 짜증나고 답답하기보다는 즐거운 게 좋지 않을까라는 생각도 들었다.

728x90
반응형

'책 리뷰 > 클린코드' 카테고리의 다른 글

5장 형식 맞추기  (0) 2022.03.01
4장 주석  (0) 2022.02.27
3장 함수  (0) 2022.02.22
2장 의미 있는 이름  (0) 2022.02.20
노마드 코더 클린코드 시작  (0) 2022.02.18
728x90
반응형

클린코드 책 인증~

728x90
반응형

'책 리뷰 > 클린코드' 카테고리의 다른 글

5장 형식 맞추기  (0) 2022.03.01
4장 주석  (0) 2022.02.27
3장 함수  (0) 2022.02.22
2장 의미 있는 이름  (0) 2022.02.20
1장 깨끗한 코드  (0) 2022.02.20
728x90
반응형

간단한 BFS 문제이다.

S에서 G로 가는 최단경로의 길이를 출력해주면 된다. 경로가 없다면 No Exit 출력

from collections import deque

def bfs(i, j):
    d = [(-1, 0), (1, 0), (0, -1), (0, 1)]
    q = deque()
    q.append((i, j))
    check[i][j] = 0
    while q:
        y, x = q.popleft()
        for dy, dx in d:
            Y, X = y+dy, x+dx
            if (0 <= Y < R) and (0 <= X < C) and graph[Y][X] != 'X' and check[Y][X] == -1:
                check[Y][X] = check[y][x] + 1
                if graph[Y][X] == 'G':
                    return check[Y][X]
                q.append((Y, X))
    return None

for _ in range(int(input())):
    R, C = map(int, input().split())
    graph = [input() for a in range(R)]
    check = [[-1]*C for b in range(R)]
    
    for i in range(R):
        for j in range(C):
            if graph[i][j] == 'S':
                ans = bfs(i, j)
                print(f"Shortest Path: {ans}" if ans else "No Exit")
728x90
반응형
728x90
반응형

pythonanywhere 사이트에서 flask로 만든 사이트를 쉽게 배포할 수 있다.

 

1 https://www.pythonanywhere.com에 접속하여 회원가입 후 로그인

2 소스파일을 압축한 다음 아래 그림과 같이 업로드하고, Open Bash console here를 클릭

image

3 압축 해제 -> 가상 환경 생성 -> 가상 환경에 필요한 라이브러리를 설치

image

4 Web으로 넘어가 Add a new web app -> Next -> Manual configuration -> Python 3.7 -> Next 순으로 진행

image

5 그러면 설정이 가능해지는데 소스 코드, 가상 환경 경로를 수정해준다

image

6 WSGI configuration file을 클릭

image

괄호 친 코드를 주석 처리

image

맨 아래 FLASK 부분 아래와 같이 수정하고 Save

image

7 Web으로 넘어와 Reload를 클릭하면 끝이다!

image

 

잘 접속되는 것을 확인할 수 있다!!

 

github: https://github.com/kimjinho1/flask-study/tree/master/pythonanywhere

 

GitHub - kimjinho1/flask-study: Flask study

Flask study. Contribute to kimjinho1/flask-study development by creating an account on GitHub.

github.com

728x90
반응형

'' 카테고리의 다른 글

MVC란?  (0) 2021.11.28
728x90
반응형

MVC는 Model View Controller의 약자로 애플리케이션을 세 가지의 역할로 구분한 디자인 패턴 중 하나입니다.

Model: 데이터베이스

View: 사용자가 보는 화면(UI)

Controller: Model이 데이터를 어떻게 처리할지 알려주고 그 결과를 View에 전달해주는 역할

-> 접근 URL에 따라 비즈니스 로직을 수행

 

아래의 그림처럼 사용자가 Controller를 조작하면 Model을 통해서 데이터를 가져오고 그 결과를 View에 전달해서

사용자에게 화면을 보여주는 방식입니다.

728x90
반응형

'' 카테고리의 다른 글

pythonanywhere에 flask 사이트 배포하기  (0) 2021.12.09
728x90
반응형

도커파일(Dockerfile)이란 사용자가 도커 이미지를 쉽게 만들 수 있도록 도와주는 템플릿입니다.

 

기본 명령어

FROM -> Dockerfile이 어떤 이미지를 base image로 사용할 것인지 명시해줌

# FROM <image>[:<tag>] [AS <name>]

# EX)
FROM ubuntu
FROM ubuntu:18.04
FROM nginx:latest AS ngx

 

COPY -> <src>의 파일, 디렉토리를 <dest> 경로에 복사

# COPY <src>... <dest>

# EX)
COPY 1.txt /test/1.txt
COPY my-dir /test-dir

 

RUN -> 명시한 커맨드를 도커 컨테이너에서 실행

# RUN <command>

# EX)
RUN pip install numpy
RUN pip install -r requirements.txt

 

CMD -> 명시한 커맨드를 도커 컨테이너가 시작될 때 실행

하나의 도커 이미지에서 하나의 CMD만 실행 가능하다.

# CMD <command>

# EX)
CMD python main.py

 

WORKDIR -> 이후 작성될 명령어를 컨테이너 내의 어떤 디렉토리에서 수행할 것인지를 명시해줌

# WORKDIR /path/to/workdir

# EX)
WORKDIR /home/test

 

ENV -> 컨테이너 내부에서 지속적으로 사용될 환경 변수의 값을 설정

# ENV <key> <value>
# ENV <key>=<value>

# EX)
ENV LANG ko_KR.UTF-8
ENV LC_ALL ko_KR.UTF-8

 

EXPOSE -> 컨테이너에서 뚫어줄 포트/프토로콜을 지정

프로토콜을 지정하지 않으면 TCP가 디폴트로 설정됩니다.

# EXPOSE <port>
# EXPOSE <port>/<protocol>

# EX)
EXPOSE 8080

 

Dockerfile 작성 예시

# base image를 ubuntu 최신 버전으로 설정
FROM ubuntu:latest

#  apt-get update 명령어 실행
RUN apt-get update

# 도커 컨테이너가 시작될 때, "Hello World!" 출력
CMD ["echo", "Hello World!"]

위와 같이 Dockefile을 생성한 후 아래 명령어를 실행해주면 도커 이미지가 생성됩니다.

docker build -t test-image:v1.0.0 .

설명하자면 이름이 my-image고 태그가 v1.0.0인 이미지를 현재 경로에 있는 Dockerfile로부터

빌드하겠다는 명령어입니다. 

 

이미지가 생성되고 나서 아래 명령어를 통해 도커 컨테이너를 실행하면

Hello World!가 출력되는 것을 확인할 수 있습니다.

docker run test-image:v1.0.0

728x90
반응형

'MLOps' 카테고리의 다른 글

도커(Docker) 설치, 명령어  (0) 2021.11.18
MLOps란?  (0) 2021.11.16
GCP 인스턴스, 스토리지 버킷 생성하기(ssh 접속, gsutil, 권한 설정)  (0) 2021.06.08
728x90
반응형

오늘은 MLOps 공부 그 첫 번째 도커에 대해 간단히 알아보도록 하겠습니다.

우선 도커는 리눅스의 응용 프로그램들을 프로세스 격리 기술들을 사용해 컨테이너로 실행하고 관리하는

오픈 소스 프로젝트입니다. 사용해보시면 느낌이 확 오는데 가상 머신에 비해 배포하는 것이 너무 편합니다.

 

도커 설치

도커를 리눅스 환경에 설치하는 방법은 아주 간단합니다. 

sudo wget -qO- http://get.docker.com/ | sh

 위 명령어를 실행하면 바로 설치가 됩니다. 설치 후 아래 명령어를 실행시켰을 때 아래 이미지처럼 출력되면 끝입니다.

sudo docker run hello-world

 

명령어

docker run -> 도커 컨테이너를 실행

많은 옵션들이 있는데 아래 명령어로 예시를 들자면 

docker run -it --name test ubuntu:latest

-it -> 컨테이너를 실행시키는 동시에 interactive 한 터미널로 접속

--name -> 컨테이너 id는 알아보기가 어렵기에 구분하기 쉽도록 이름을 지정

-it 옵션을 붙였기에 명령어 실행 후 새로운 터미널에 접속된 것을 확인할 수 있습니다.

컨테이너의 이름이 test1인 것을 확인할 수 있습니다.

 

docker images -> 도커 이미지 리스트를 출력

위에서 도커가 설치됐는지 확인할 때 생성한 hello-world 이미지와

docker run 명령어 예시를 들 때 생성한 ubuntu 이미지가 출력되는 것을 확인할 수 있습니다.

 

docker ps -> 실행 중인 도커 컨테이너 리스트를 출력

확인을 위해 아래 명령어를 실행시키고 나서 docker ps 명령어를 실행하면 

docker run -it -d --name test1 ubuntu:latest

docker run 명령어에서 -d 옵션은 백그라운드에서 컨테이너가 계속 실행되도록 해준다.

test1 컨테이너가 출력되는 것을 확인할 수 있습니다.

옵션으로 -a를 넣고 실행하면 실행되었던 컨테이너까지 출력이 됩니다. 

 

docker stop -> 실행 중인 도커 컨테이너를 중단

docker stop [컨테이너 id]와 같은 방식으로 사용하는데 id는 다 칠 필요 없고 겹치는 숫자가 없을 때까지만

입력해주면 됩니다. 예를 들어 1234, 1289 2개의 컨테이너가 있다면 123 까지만 처도 1234 컨테이너가 중단됩니다. 

 

docker rm -> 도커 컨테이너를 삭제

test, test1 컨테이너를 중단하니 docker ps, docker ps -a 명령어에서 출력되지 않는 것을 확인할 수 있습니다.

 

docker rmi -> 도커 이미지 삭제

ubuntu 이미지가 삭제된 것을 확인할 수 있습니다.

 

만약 아래와 같은 에러가 뜬다면

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/images/json": dial unix /var/run/docker.sock: connect: permission denied

아래 명령어를 실행시키시면 됩니다. 저는 이걸로 해결됐습니다.

sudo chmod 666 /var/run/docker.sock

 

728x90
반응형

'MLOps' 카테고리의 다른 글

도커파일(Dockerfile) 작성  (0) 2021.11.21
MLOps란?  (0) 2021.11.16
GCP 인스턴스, 스토리지 버킷 생성하기(ssh 접속, gsutil, 권한 설정)  (0) 2021.06.08
728x90
반응형

MLOps는 머신러닝 시스템 개발과 시스템 운영을 통합하는 것을 목표로 하는 머신러닝 엔지니어링 방식입니다.

머신러닝 모델을 안정적이고 효율적으로 배포 및 유지하는 것을 목표로 한다고 보시면 될 것 같습니다.

 

MLOps의 구성 요소로는 크게 데이터, 모델, 서빙 3가지로 나눌 수 있는데

아래와 같이 아주 많은 플랫폼, 오픈 소스들이 존재합니다. 

데이터

  • 데이터 수집 파이프라인(ETL Pipeline) -> Sqoop, Flume, Kafka, Flink, Spark Streaming, Airflow
  • 데이터 저장 -> MySQL, Hadoop, Amazon S3, MinIO
  • 데이터 관리 -> TFDV, DVC, Feast, Amundsen

모델

  • 모델 개발 -> Jupyter Hub, Docker, Kubeflow, Optuna, Ray, katib
  • 모델 버전 관리 -> Git, MLflow, Github Action, Jenkins
  • 모델 학습 스케즐링 관리 -> Grafana, Kubernetes

서빙

  • 모델 패키징 -> Docker, Flask, FastAPI, BentoML, Kubeflow, TFServing, seldon-core
  • 서빙 모니터링 -> Prometheus, Grafana, Thanos
  • 파이프라인 매니징 -> Kubeflow, argo workflows, Airflow

여기서 서빙이란 개념은 조금 낯선데 다른 애플리케이션에서도 ML 모델을 사용할 수 있도록 모델을 배포하거나,

모델 API를 제공한다고 이해하면 될 것 같습니다.

 

그리고 위의 기능들을 제공해주는 Aws SageMaker, GCP Vertex AI, Azure Machine Learning 등이 있습니다. 

728x90
반응형
728x90
반응형

기본적인 그리디 알고리즘 문제이다. 

for _ in range(int(input())):
    j, N = map(int, input().split())
    li = []
    for i in range(N):
        r, c = map(int, input().split())
        li.append(r*c)
    li.sort(reverse=True)
    cnt = 0
    while j > 0:
        j -= li[cnt]
        cnt += 1
    print(cnt)
728x90
반응형
728x90
반응형

기본적인 그래프 탐색 문제이다. 최단거리를 찾는 문제이므로 BFS로 풀었다.

from collections import deque

def bfs():
    q = deque()
    q.append((0))
    while q:
        node = q.popleft()
        n = li[node]
        if check[n] == 0 and node != n:
            q.append(n)
            check[n] = check[node] + 1
            if n == K:
                return ;
    
N, K = map(int, input().split())
li = [int(input()) for _ in range(N)]
check = [0]*N
bfs()
print(check[K] if check[K] else -1)
728x90
반응형

+ Recent posts