티스토리 뷰

Back-end

[패스트캠퍼스 6번쨰 수업]

jhkang-dev 2018. 11. 10. 15:50

안녕하세요 강정호입니다. 오늘 패스트캠퍼스에서 배우는 6번째 수업에 대해 포스팅 할게요


1교시


- 프로그래밍이 무엇인가? 

1) 요구사항을 아키텍쳐에 기반하여 구현하는 것

2) 아키텍쳐의 중요성 : 프로그래머가 곧 아키텍트이다. 

3) 알고리즘 문제 푸는 것은 어떤 아키텍쳐를 생각해서 구현하는 것과는 다르다

알고리즘이 논리적인 사고 방식을 표현하는 것에는 적합하다.


- 참조 아키텍쳐 : 비슷한 도메인으로 구현한 것에서 아키텍쳐를 모방해 온다.

1) 우리한테 맞는 부분을 가져오고, 그렇지 않은 부분을 제외한다.


- 개발 사이클을 짧게 잡자!

1) 회원가입, 로그인을 2주동안 만들고 고객에게 보여주자.

2) 고객이 보고, "이건 아닌데?" 하면서 피드백을 받는다.

3) 나머지 2주 동안 다른 기능을 개발한다.

4) 피드백을 바탕으로 리팩토링을 한다.

5) 이러한 과정을 통해서 잘못된 아키텍쳐가 있다면 수정한다. 리팩토링 --> 피드백 과정을 지속적으로 반복.


- 리팩토링

1) 수정을 했는데 원래처럼 잘 동작해야 한다.

2) 수정한게 잘 동작한다는 것은? 

3) 프로그램이 완벽하다는 것은 증명할 수 없다.

4) But 테스트한 코드는 잘 동작한다를 증명할 수는 있다.


- 테스트 코드

1) if , else일 때 테스트코드는 2개를 작성해야 한다.

2) 테스트 커버리지 : 테스트 코드가 얼마나 많은 흐름을 커버하는가?

3) 사실 제대로 테스트를 하려면, 모든 조건문에 대해서 흐름을 커버해야 하지만, 어렵다. 그렇기 때문에 내가 작성한 코드에 대해서 1번쯤은 실행한다를 목표로 테스트 커버리지를 한다.

4) 테스트 커버리지 100%는 불가능하다.


- 점진적, 통합, 테스트 개발의 중요성!!

1) 리팩토링을 하니 Test를 해야 하게된다.

2) 그럼 테스트부터 만들자?! 미리 테스트 코드를 만든다는 것은 기능에 대한 정의를 미리한다는 것. 즉 요구사항 설계를 먼저한다는 것.

3) 그래서 TDD가 등장하기 시작 : TDD를 하기 위해서는 내가 어떤 기능을 만들지 설계가 작성되어야 한다. TDD를 한다는 것은 회사의 문화를 바꾸는 것.

4) A -> B -> C 

- C를 수정하게 되면 C만 테스트 하는게 아니라, C와 관련된 모든 A,B 등도 테스트 해야 한다. 그것이 바로 "회귀 테스트" 라고 한다.

5) 테스트 코드를 자동화? 

- CTiP 환경

- Jenkins : 쉽게 테스트하고 배포할 수 있다. --> 이러한 일련의 과정을 "파이프 라인"이라고 한다.

- 새로운 프로젝트를 하기 위해서는? 아키텍쳐, TDD, Jenkins 등을 하려면 내가 스스로 개발 문화를 만들어야 한다.


6) 인터페이스 생성 --> 구현 -->테스트 코드 작성

1) 인터페이스로만 테스트 코드를 작성하면 구현되어 있지 않기 때문에 실패한다.

2) 인터페이스를 차츰 구현하면서 테스트 코드를 작성하여 실행시키면서 개발해 나간다.


- 개발서버에서는 작동하는데 운영서버에서는 작동을 안한다?

1) 이는 굉장히 다양한 이유가 있을 수 있다. --> 환경변수가 달라서 그럴 수도 있고

2) 내 컴퓨터가 개발환경과 똑같다면 얼마나 좋을까? 그러면 내가 개발한 것이 동작을 안할 수가 없다.

3) 가상 머신은 속도가 굉장히 느리다.  --> 그러다가 도커가 등장한다.

4) 내 개발환경과 운영환경에 도커를 쓰면 그 둘이 동일해진다. --> 그래서 배포환경에서 도커를 사용한다.


- Docker

1) https://docs.docker.com : 도커 문서

2) Get Started with docker

Docker 엔진 위에서 격리된 환경에서 따로 따로 APP이 돌아간다. 그러면서 자원이 공유된다. 별도로 Guest OS를 설치하지 않고 기본 Host OS를 사용한다.

3) docker run hello-world : 퍼블릭 레포지토리에서 이미지를 받아와서 실행하는 것 --> 실행되고 종료되기 때문에 docker ps에도 나타나지 않는다.

4) docker ps --all : 실행되었던 도커 이미지를 보여준다.

5) 도커 파일이 이미지를 만드는 것이다.





2교시(https://docs.docker.com/get-started/part2/)


# Use an official Python runtime as a parent image

FROM python:2.7-slim   이 이미지 안에

# Set the working directory to /app
WORKDIR /app  #workdir

# Copy the current directory contents into the container at /app
COPY . /app   

# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]


Expose 80 : 포트를 80포트로 설정.


CMD python, app.py : python으로 app.py를 실행하여라.



app.py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():  #슬래시 요청이 오면 이 함수가 실행된다
    try:
        visits = redis.incr("counter")  #count의 키값을 하나씩 증가한다. 방문자 수를 증가시키는 것
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \
           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80) #0.0.0.0 이기 때문에 어디서든 접속할 수 있도록 한다.



빌드하기

docker build -t friendlyhello .

: . 은 현재 폴더에서 도커 이미지를 실행


Run the app

내 컴퓨터 안에 있는 도커에서 실행된다.

docker run 4000:80 friendlyhello


localhost:4000 을 입력하면 실제로 내 컴퓨터의 도커의 80포트에 접속하는 것



$ docker ps : 도커 이미지에 대한 컨테이너 아이디 c434


$ docker exec -it c434~~~


도커 컨테이너 : 리눅스 커널은 기반으로 사용하고 커널 위에 파이썬이 설치된 것이고, 그 앱을 실행 하는 것이다.


$ docker container stop 컨테이너 아이디 : 해당 컨테이너를 종료한다.


내가 만든 도커 이미지를 다른 서버에서 갖다 쓰고 싶을 떈?

- $ docker login

- $ docker tag image username/repository:tag


ex) docker tag friendlyhello wwwkang8/myhello:0.1

도커 이미지에 태그를 붙여주는 것이다.



$ docker push wwwkang8/myhello:0.1

: 도커 이미지를 올리는 명령어


$ docker ps


$ docker ps -all


$ docker ps -all



Part 3 : https://docs.docker.com/get-started/part3/


version: "3"
services:
  web:
    # replace username/repo:tag with your name and image details
    image: username/repo:tag
    deploy:
      replicas: 5
      resources:
        limits:
          cpus: "0.1"
          memory: 50M
      restart_policy:
        condition: on-failure
    ports:
      - "4000:80"
    networks:
      - webnet
networks:
  webnet:


replica : 도커 이미지가 5개가 실행된다. 내부적으로 파이썬 포트는 80포트로 실행된다. 


network : 도커 이미지간의 통신을 해야하기 때문에.


$ docker swarm init : 


$ docker service ls : REPLICAS가 5개가 되어 있다. 그래서 서버가 하나가 죽어도 서비스가 죽지 않도록


컴퓨터가 1개 있을 때는 도커 스웜이 필요가 없다.

도커 스웜을 사용할 때 ---> 가상머신



$ docker swarm init : 매니저에 의해서 결정되었다.


- 리플리카로 100개 시켜봐


가상 머신 실행하는 것도 생성 가능.



레디스는 저장소이다. 실제 데이터는 호스트 운영체제 밖에 저장될 수 있도록 해야한다. 이미지


테스트 코드작성할 때는 Mockito를 공부하기










3교시


<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<!--<dockerHost>https://192.168.99.100:2376</dockerHost>-->
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
</configuration>
<executions>
<execution>
<id>default</id>
<phase>install</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>



<imageName>${docker.image.prefix}/${project.artifactId}</imageName>
<!--<dockerHost>https://192.168.99.100:2376</dockerHost>-->
<dockerDirectory>src/main/docker</dockerDirectory>


nginx:
image: nginx:1.13
restart: always
ports:
- 80:80
- 443:443
volumes:
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
depends_on:
- app
links:
- app

nginx 서버가 8080포트로 대기하고 있고

9090으로 프락시 해준다.


왜 nginx 서버 포트로 8080을 해놓았느낙?


pom.xml : 도커 플러그인 추가하면 만들어진 도커 이미지가 내 로컬에 저장된다.

만들어진 이미지를 내 도커 컨테이너에 띄운다.




4교시



Profile은 언제 

@Profile("local")을 적고 하니 


spring.profiles:prod

spring.profiles.include


배포할 때 프로파일 설정이 중요하다. 개발환경과 운영환경이 다르기 때문이다.


메이븐 빌드 도구에서도 프로파일 설정을 할 수 있다. 로컬에 대한 부분만 따로 모아서 


빌드 시스템이 고장나면 빌드할 수 있는 방법이 없다. --> 한번 만들어진 빌드파일안에 모든 설정이 들어있다. 그래서 로컬에서 다시 빌드해서 배포할 수 있다.


메이븐 빌드 프로파일, 그래들 빌드 프로파일, 스프링 빌드 프로파일



MOCKITO


- 웹 개발을 할 때 레이어드 아키텍쳐를 쓴다. 레이어 별로 컨트롤러, 서비스, 레퍼지토리를 사용한다.


모키토의 핵심기능

- 가짜 객체를 만들어준다.

- 서비스를 가짜로 만들어준다.


우리가 말하는 테스트는 통합테스트가 아닌 단위테스트이다.


유용한 사이트 : https://www.popit.kr/



https://www.popit.kr/spring-rest-docs/  이거 보면서 Mock 공부 해보기


Scouter : 해당 어플리케이션이 잘 동작하는지 모니터링하는 도구


5교시(운영 키워드 공부)


- 마스터, 슬레이브 데이터소스

- 데이터가 너무 많아졌다? --> 샤딩 이란 것을 해야한다.

- DB를 나눌 때 샤딩 키가 중요하다.

게임 아이디, 게시판 아이디를 기준으로 디비를 생성해야 한다.

- DB 하나에 접근할 수 있는 Web API가 생긴다 --> 게임의 유저가 많아질 수록 이런 세트가 많아진다.

- RestTemplate를 이용하여 WebAPI를 호출한다.



DDD

CQRS  키워드로 공부해보기


Microservice Architect


Circuit breaker : 두꺼비집을 생각하면 된다. 문제가 있으면 Web api를 호출하지 못하게 하는 것.



스프링 네이티브 클라우드




<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>

QueryDSL을 사용하기 위한 메이븐 파일

Entity를 












댓글