2020.05.20 TIL & 소박한 소프트웨어 공학

solar·2020년 5월 21일
1

TIL

목록 보기
1/1

강의

소박한 소프트웨어 공학

과학 - 개념 & 원리적인 것

공학 - 과학을 바탕으로 검증된 것들을 공학적으로 개발하고 제품화하는 것. 데이터로 부터 정보를 만들어 내는 것

CS - 이론적인 것에 가까운 과목

CE(Computer Engineering) - 우리가 학습하려는 과목

EE(Electronig Engineering) - 전자공학과에서 배우는 과목

"공부할 때 이론적인 것과 공학적인 것을 바꿔가면서 공부해야 한다."

CE를 잘 다루기 위해 공부해야 할 것들을 강의

소프트웨어 공학

  • 소프트웨어 개발이 쉬운가요?
    • 어렵다...
    • 어떤 것이?
    • 요구사항 (생각) --- 설계 --→ 아키텍처(모델, 데이터구조 설계) --- 개발--→ 코드
    • 아키텍쳐화 하는 과정이 어렵다. 모호하다.
    • 생각은 끊어져있지 않고, 이어져 있다
학계 vs 업계
  • 과학적인 측면과 공학적인 측면 두가지 중 실무에 가까운 이론임에도 불구하고, 이론이 먼저인지 실무가 먼저인지 논란이 많다.

  • 이론과 실무가 같이 발전하지 못하기 때문에

  • 현업에 있는 실무자들이 더 빨리 변화를 가져오고 새로운 것을 가져와서 적용하기 때문에 훨씬 더 빠르다. 그 후에 이론이 정립되는 편이다. (학계에서 새로운 것을 먼저 만들어 내는 것보다.)

  • 협업 요구사항을 먼저 준다고 해서... 이론적으로 먼저 배운다고해서 협업을 잘하는 것은 아니다.

  • 실무적으로 먼저 절차나 형식을 먼저 몸으로 느껴보고, 이론적으로는 어떤 내용이 있는지 알 수 있다.

SW 공학
  • 책의 1장의 내용이 완전히 바꼈다.

  • (기존) Waterfall Process

    • 이 절차들이 다 필요함에도 불구하고 잘못됐다고 배우는 이유는 실패한 사례들이 많기 때문이다.
    • 맥락이 없이 단계별로 진행하기 때문이다. 앞 단계가 다 끝난다음에 다음단계를 진행하기 때문이다. 요구사항 분석을 끝내고 설계하고, 설계를 다하고 구현하고, 구현을 다하고 테스트하고 하다보면 망하는 경우가 많다.
    • ⇒ 이러한 문제점 때문에, 단계 사이에 맥락이 끊어지면 안된다고 느꼈다. 흐름이 이어져야한다고 생각했기 때문에 다른 방식이 추천된다.
  • 요구사항 하나가 feature, specification으로 넘어가면서 얼마나 많은 내용이 필요한지 깨닫게 되었을 것이다.

⇒ 소프트웨어가 왜 필요한지에 대해 까먹는 경우가 많다. "소프트웨어 모듈 존재 이유"

소프트웨어 모듈 존재 이유

⇒ 그래서 방법론이 등장하게 된다.

요구사항을 쓰는 사람, 개발하는 사람 모두 실수하게 된다.

요구사항을 잘못 이해해서 오류가 발생하는 경우가 많다. (56%)

  • 요구사항 분석에서 발생할 수 있는 오류를 배포 이후에 알아내서 오랜 시간이 지난후에 발견하지 말고, 주기를 짧게 짧게 해서 오류를 빨리 발견하자는 것이 애자일의 기본 아이디어이다.
  • 요구사항에서 오류가 발생하는 경우 ? 고객이 자신이 원하는 것이 뭔지 잘 모를 때

제한적인 기간과 비용에서 품질이 높은 코드를 만들어 낼지 고민하는 것이 공학자들의 문제

⇒ 소프트웨어를 만들 때, 끊어진채로 개발하면 안되겠다. (이전에는 건축 설계 하듯이 만들어 왔었다.)

애자일 방법론이 등장하게 된 것

애자일 방법론

빠른 피드백을 주고받고 점진적으로 개선해나가는 방식이 더 빠르게 오류를 잡을 수 있는 방법이다.

아무리 초반에 오랜 시간을 써서 설계를 잘해도 뒤에가서 분명 설계를 고치게 될 것이다. 그러니깐 하루 설계하고 하루 구현하고 다시 설계하고 다시 구현해보자

EXTREAM PROGRAMMING

  • 애자일이 나오기 전에 썼던 방법들 (XP)

소규모 릴리즈 : 짧은 주기 배포 → 1일 1배포 목표

메타포 : 서로 다 이해할 수 있는 표현법이 필요

짝 프로그래밍 : 의사소통 능력을 키우기위해서라기보다 프로젝트를 잘 해내기 위해서 하는 것. 서로 다른 이해도를 가지고 있을 때 프로젝트를 잘 이해하기 위해서 할 수 있다.

주 40시간 : 40시간이 넘어가면 집중력이 떨어진다. → 테스트를 써서 집중력있게 빠르게 끝내도록 하자

  • XP의 목표 : 변경이 일어나는 지점이 발생하면 비용이 점점 기하급수 적으로 늘어나기 때문에, 변경이 계속 되더라고 일정한 시간안에 고쳐서 만들 수 있게 하는 것이 목표이다.

애자일 실천법

  • 왼쪽 - 기술적인 관점 "어떻게하면 더 좋은 개발환경을 유지할 수 있을까"
  • 오른쪽 - 소셜 관점 "어떻게 좋은 관계를 유지할 수 있는지"
  • 소멸 차트 : 할일 중에 완료된 것들을 데일리로 정리하면 언제 끝날 수 있는지 예측할 수 있다.
    • 기간 내에 못끝낼 것 같으면 조정을 할 수 있게 된다.

애자일 선언문 - 스크럼

  • 행동한 내용으로 결과물이 나오면 좋은 것이다.
  • 결과물을 만들어 내려고 행동할 필요는 없다. → 문서를 남기려고 스크럼하지 말자. (의미 없음)
  • 계획서를 만들어서 전부 지키려고 하지 말고, 당장 오늘 할 것을 디테일하게 만들고, 3주 뒤에 할 일은 간략하게 계획하자. 어짜피 다 바뀌게 되어있다.

SPIRAL 나선 모델 - 점진적 개선

  • 첫째날 프로토타입 도구를 이용해서 요구사항에 대한 분석을 먼저 해보자(어도비 xd 등...) 코드 한줄없이 한시간만 투자하면 뷰를 만들 수 있다.

  • 검증해야할 것이 무엇이고, 설계하면서 시나리오를 만들어서 데모를 준비하는 것이다.

  • 그리고 필요한 요구사항들을 채워나가자

⇒ 항상 새로운 것을 만드려고 하지말고, 항상 점진적으로 살을 붙여서 리모델링해 나가는 방식으로 개발하자

빠른게 중요한 것이 아니다.

애자일 설계와 개발

  • 코드에서 냄새가 많이 난다. (음식에 비유) → 부패한 코드 → 청소하자 클린코드
  • 계속해서 코드를 변경해나가면 부패한 코드가 나오기 때문에 이를 정리하기 위해 클린 코드를 만드려고 노력하자는 것이다.
  • 처음부터 클린한 요구사항을 주면 좋지 않을까? → 그럴일은 없다. 포기하자. 잘못이해한 요구사항이 반드시 발생하게 된다.
  • 가능한 명료하고 명확한 코드를 클린코드라고 한다. 처음 요구사항부터 개발할 일 보다 이미 만들어져 있는 서비스에 추가되는 요구사항을 개발하는 일이 많기 때문에 클린 코드를 유지하는 것이 좋다.

실제 개발 업무 시간

  • 계획과 안정화를 위한 시간이 꽤 필요하다.
  • 내가 생각할 때, 5일이 있으면 실제 개발가능한 시간은 3일이라는 것을 생각하고 고려해서 계획을 해야한다는 것이다.

KISS, YAGNI, DRY

  • 요즘은 요구사항을 분석해서 아키텍쳐를 만들어내는 요구사항 분석가 전문인들이 따로 있을 정도이다.
  • 기능 외에 비기능도 있다.
기획 / 요구사항에서 설계하기
  • 구성도, 구성도의 흐름으로 표현하고, 흐름을 표현하는 흐름도, 흐름도를 표현하는 상세도 를 작성해라
시스템 구성도 예시 C4 모델
  • 시스템 구성도의 핵심 - 유저를 항상 표시해야한다.

  • 관리자, 고객(가입전, 가입후, 결제전, 결제후) 등 구체적으로 사용자들을 나눌 수 있어야 하고, 사용자별로 동작이 달라지기 때문에 이를 고려해서 설계를 해나가야 한다.

  • 자꾸 유저를 1명이라 생각하고 설계를 하려고 하면 잘못된 설계가 될 것이다.

  • 같은 프로젝트를 모두가 시나리오에 따라 "유저의 동작 흐름"을 설명할 수 있는 표현만 나타내면 된다. 한 번 그려보도록 하자 (형식은 상관없음)

DIAGRAM

전체 동작하는 흐름을 나타내는 설계와 기능별로 디테일하게 그린 설계도를 둘 다 그려야한다. 그래야 이해가 달라진다.

⇒ 이해를 위해 그림을 그려보는 것을 추천한다. 같은 것을 이해하고 있는 것인지 나타내는 것이 중요하다.

⇒ 시야의 높이도 중요하다. (높은 시야에서 보는 것과 구체적인 시각으로 바라보는 시각의 차이가 발생하기 때문에 그러면 이해 차이가 발생한다.)

⇒ 높은 시야에서 모두 이해를 하고, 점진적으로 층별 이해를 해나가는 것이 좋다.

백로그 EPIC → STORY → TASK

  • 백로그 : 모든 해야할 일

  • ECPI : 큰 단위의 일 (100일 동안 할 일), 전체 해야할 일의 제목

    • OAuth 기능구현
  • STORY : 데모 시나리오가 되는 정도의 일

    • 가입되지 않은 사용자가(사용자) 로그인을 하기 위해서(목표) github 로그인 버튼을 누른다.(행동)
    • 사용자, 행동의 이유, 목표 가 있어야 한다.
    • 계획할 때 이 3가지 항목을 넣어서 스토리를 만들어보자
    • 개발할 거리를 추출해 내는 것 "플래닝"
    • 그 스토리가 시스템에서 통과(검증)하려면 단계별로 어떤 것들이 필요한지 조건들을 정리하게 된다. ⇒ 이렇게 정해진 조건들이 테스트 케이스가 된다.
    • 플래닝 회의 - 스토리에 따라서 각 FE, BE 별로 해야할 일을 정하는 것 (보통 3일 정도 한다.)
  • TASK

    • 스토리 안에서 기능을 쪼개서 할 일을 만드는 것이 TASK 이다.
    • 실제로는 기능요구 사항보다 정상적으로 스토리가 동작하기 위해서 통과해야하는 조건들이 존재하기 때문에 테스트 요구사항이 더 많아진다.

비기능 요구사항

  • 당연히 요구되어져야하는 내용들이 기획서에 없는 경우가 있다.

    • ex) 비밀번호
      • 서버에 전송할 때 암호화해서 전송해야한다.
      • 서버에 저장될 때 암호화해야한다. (단방향? 양방향?)
      • 입력할 때 감춰야한다.
    • 숨겨져있는 기능을 찾아내서 구현하고 테스트하는 것이 개발자들이 해야할 일이다.
  • 100만 명의 유저가 동시에 접속했을 때, 정상적으로 돌아가기 위해서 (요구사항에는 적혀있지 않지만) 개발자는 이를 고려하고 만들어야 한다.

  • 코드의 품질을 높여주진 않지만, 서비스의 품질을 높여준다. ⇒ 이를 신경쓰지 않으면 언젠가 큰 코 다친다. 꼭 확이해야하는 사항이다.!!!!!!!!!!!!!!!!!

  • 비기능 요구사항도 task 로 관리하면 좋다. 하지만 가정하고 넘어가는 경우가 많다. "~~조건과 ~~가정에서 ~~해야한다"는 것은 명시해야한다. 하지만 상당부분은 가정하고 넘어가는 경우가 많다. ⇒ ~~가정했고, 그래서 ~~기능은 ~~했다. 라고 답할 수 있어야한다. (BE 중요!!!! - 다시 듣고 정리하자)

  • 해당 비기능 요구사항이 필요한 순간에 고민해보자. 비기능 요구사항들 중에서도 필요한 것들은 기능 요구사항보다 먼저 고민해야할 상황도 있다. 팀에서 같이 고민하고 가정치를 만들어서 우선순위를 잡아야할 것이다. (꼭 일의 우선순위 뒤로 가가야할 것은 아니다.)

소프트웨어 개발 - V 패턴

  • 왼쪽의 단계와 짝 지어서 모든 단계마다 검증이 필요하다.

  • 우리가 설계했으면 단위 테스트, integration 테스트, system test를 해야한다.

  • 위로 올라갈 수록 시간이 오래걸리고, 피드백 받는데 오래걸리지만, 실제 시스템에 가까운 테스트이다.

  • 위에 있는 수준의 테스트도 해야하지만 밑에 단위의 테스트도 진행해야 한다. 모두 고려해야 한다.

주의사항

요즘 v 패턴은 더 복잡해졌다. 학습할 때 조심할 것. 한글 위키는 업데이트가 느리다. 영문 위키는 최신 v패턴 자료가 나온다. 공부는 영문 위키를 확인하자.

계속해서 자료가 바뀌기 때문에 엔지니어는 계속해서 공부해야 한다.

소프트웨어 개발 테스트 패턴과 CI

  • 인수 테스트 조차 코드로 할 수 있지 않을까? ⇒ 엔지니어의 범위

  • CI를 강조한다.

  • 코드만 합치는 것이 아니라 이 테스트까지도 모두 Integration이 되어야 CI라고 말하자

  • ⇒ 그래서 "DEVOPS"가 나온다.

  • 엔지니어는 어디까지 일해야할까?

  • 테스트와 CI는 모두 자동화해야하고, input과 output만 엔지니어가 적용해줘야 한다. (이상적이지만 어려운 일이다.)

  • 이를 잘하려면 다 잘 알아야한다. 인프라, 서버 구성, DB, 아키텍쳐, 코드를 모두 잘 알아야 잘 돌아갈 수 있다.

  • 이런 시스템만 관리해주는 분들이 계시지만 BE가 많이 알고 있어야 한다.

⇒ 결론 "소프트웨어 유지보수란" 지금처럼만 잘 동작하도록 만드는 것이 아니고, "변화하는 세상에서 유용하도록 만드는 것"이다.


단위 테스트

  • print 쓰지말자. 습관이 된다. 성능에 악영향을 준다. 디버깅을 하자
smoke testing
  • 전기를 켜보면서 연기가 발생하는 여부로 정상인지 아닌지 테스트하는 것.
  • 이러지 말자

Software Testing

  • 통합테스트와 같이 길고 큰 범위의 테스트를 하지말고, 더 짧고 빠르게 돌려볼 수 있는 테스트를 해보자 - "Unit Test"의 취지
  • QA 팀이 있어서 end to end 단의 테스트를 해주는 회사도 있지만, 엔지니어는 짧은 기능으로 테스트하면서 개발해야 한다.

좋은 테스트 A-TRIP

  • 서로 다른 테스트끼리 연관성이 없어야 한다. 모든 테스트 코드는 "독립적"으로 돌아가야 한다.
xUNIT
  • 에릭감마 - 말을 좀 더 풀어서 쓰는 느낌. 켄트백 - 책이 좀 어려움

리팩터링

  • 반드시 단위 테스트가 존재해야 한다. !!!!!

  • 테스트가 없이 리팩터링 한 것은 리모델링이 아니라 불법개조한 것이다.

  • 지속적인 통합(CI)이 가능해야 한다.

  • IDE가 제공하는 리팩터링 기능을 이용하자

  • test code가 없다면 리팩터링 하려고 하지 말자.

  • test code와 리팩터링은 뗄 수 없는 고인돌 관계이다.

무엇을 테스트 해야할까? 어디서부터 어디까지 얼마나

  • 전원 버튼을 테스트하려면 뭘 테스트해야할까?
    • 실제로 QA팀은 무엇을 테스트할지 계산한다.
    • 한번 누를 것이지, 두번 세번 누르면 어떻게 될지, 10초 1000초 누르고 있으면 어떻게 될지 → 테스트 케이스가 무한대로 늘어난다.
    • 구매버튼 10번씩 눌러보고 중복구매 되었다? 안되네요? 실제로 이런식으로 테스트한다.
    • 사용자들도 이런 식으로 사용하는 경우가 있기 때문에
    • 테스트라는 것은 범위를 정하고 무엇을 테스트할지 명확히 하는 것이 중요하다.
    • 안의 내부 동작방식은 다르다.
화이트박스 테스트
  • 개발자가 하는 테스트
  • 어떻게 돌아가야하는지 내용을 알고 있기 때문에 어떤식으로 테스트해야할지를 안다.
블랙박스 테스트
  • 어디까지 테스트할지 모르기 때문에 범위를 잘 지정해야한다.

무엇을 테스트해야하는가 - 6가지 Right - BICEP

  • B : 값이 들어갈 때, input에 따른 output이 달라지는데, 그 값들에 따라서 경계가 생긴다.
    • 값을 안넣는 경우, 많이 넣는 경우, 길게 / 짧게 넣는 경우에 따라서 정상적으로 동작하는지를 봐야한다.
  • 실행하지말고 내가 기대한 것이 나오는지 확인할 수 있는 코드를 쉽고 빠르게 짜자
  • 테스트를 잘 하려면 객체지향에서 객체를 나누고, 인터페이스를 나누고 이런 기법들을 써야지만 테스트가 가능해진다. 그렇지 않으면 객체끼리 서로 들러붙어 있어서 모든 객체를 테스트해야하는 문제가 발생한다.
  • 한 클래스, 한 모듈만 테스트할 수 있게 만들어야 한다. "이것이 단위테스트의 시작"이다.
TEST DOUBLE
  • 테스트를 위해서 임시적으로 존재하는 것들 (스턴트)
FAKES
  • 실제 동작에 가까운 가짜 구현체

  • 가짜 객체가 DB에 연동하는 DAO 객체라면, 실제 DB에서 값을 가져오지 않고 메모리에서 값을 가져오지만 동작은 동일하게 동작하는 구현체이다.

STUBS
  • fake 중에서도 특정한 한 동작만 구현하면 stub이라고 한다. DB나 네트워크 요청 request를 대체하는 것들
MOCK
  • 특정 함수의 동작을 확인하기 위해 호출
  • 목을 넣어서 영향받는 것들이 (함수를 대신 호출해주는 것)

⇒ 이러한 객체들만 이용해서 테스트를 진행하자

B - 경계조건

  • 값의 범위를 지정한다.
  • 값을 어떤 것을 넣느냐
  • 엉터리 입력값(숫자를 넣어야하는 문자를 넣는다, 이메일형식인데 틀린 형식을 넣어본다.)을 넣었을 때, 시스템이 멈추지 않고 잘 동작하는지
  • 중복된 데이터가 오면 안되는데 오는 경우, 순서가 올바르게 오는지 (주문 순서)
  • 데이터 모델을 설계할 때부터 이 범위를 넘어가는지를 고려해서 FE에서 막을지, BE에서 막을지를 확인해야 한다.

I - 역관계 확인

  • 알고리즘이 들어가는 경우
  • 지웠으면 지워졌는지 확인

C - 다른 수단을 이용한 교차 확인(cross check)

  • 바보 정렬
  • 기존의 알고리즘

E - 에러 조건을 강제로 만들기

  • ex ) 패킷을 다량을 전송해서 정상적으로 잘 동작하는지, CPU를 적게 사용해서 동작시켜본다.
  • 에러가 발생할 수 있는 환경을 구성해서 서비스가 잘 동작하는지 테스트 해야 한다.

P - 성능 특성

  • 이 것 때문에 알고리즘 테스트를 본다.

  • 비 기능 요구사항에 대해 어떻게 회귀 테스트를 할 것인지를 확인하기 위해서 성능 특성 툴을 사용한다.(?)

범위

  • float, double 을 쓸 때 조심해야한다. 비교가 잘 안되는 경우가 있다. 이진수로 표현하기 때문에 이진수로 표현할 수 없는 실수값들은 비교가 되지 않는다. 소수점 자릿수가 다른 경우

개체 수

  • 적어도 0개, 1개, n개인 경우에 대해서는 테스트 해야한다.
  • 특정 개수에 대한 테스트 ex) 볼은 4개면 안타로 된다. 4개를 초과하는 값이 들어가면 안된다.

시간(TIME)

  • Request를 만들 때는 반드시 timeout을 처리해야 한다. (중요)

Code coverage

  • 코드 커버리지 : 테스트 코드가 코드들을 얼마나 커버했는지, 테스트가 얼마나 되었는지

    즉, 테스트가 안 된 코드들을 찾아낼 수 있다.

    100%를 만들 필요는 없다. (사람 목숨을 다루는 소프트웨어는 100%를 요구하기도 한다. 항공기, 자동차, 의료시스템에 들어가는 소프트웨어)

    코드 커버리지를 높이는 것을 목표로 할 필요는 없다. (ex. 뷰)

    코드 커버리지로 필요한 모듈을 테스트하는 것은 중요하다.

    백엔드는 코드 커버리지가 높고 수월한 편이다. (fe에 비해 상대적으로)

  • 테스트 커버리지 :

  • 커버리지를 높이는 방법도 공부해야 한다.


BDD

  • Behavior Test : 테스트 시나리오를 개발자가 쓰는 것이 아니라 도메인 전문가 또는 기획자가 쓰면, 그 시나리오를 그대로 테스트 케이스로 만들어보자
  • 요구사항 문장을 그대로 테

To Do List

  • DB 설계 - ERD

  • DB에 넣을 데이터 가공

  • API 포맷 정하기

  • 전날 정리한 의논사항 FE랑 의논하기

  • 면담 질문 정리하기

  • 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 읽기

    • 3장. 스프링 부트에서 JPA로 데이터베이스 다뤄보자
      • 정리하기

ERD_version1

Schema query

-- MySQL Script generated by MySQL Workbench
-- Wed May 20 23:27:02 2020
-- Model: New Model    Version: 1.0
-- MySQL Workbench Forward Engineering

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

-- -----------------------------------------------------
-- Schema airbnb
-- -----------------------------------------------------

-- -----------------------------------------------------
-- Schema airbnb
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `airbnb` DEFAULT CHARACTER SET utf8 ;
USE `airbnb` ;

-- -----------------------------------------------------
-- Table `airbnb`.`listing`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `airbnb`.`listing` ;

CREATE TABLE IF NOT EXISTS `airbnb`.`listing` (
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(64) NULL,
  `price` VARCHAR(64) NULL DEFAULT 0,
  `discount_price` INT NULL,
  `cleaning_fee` INT NULL DEFAULT 0,
  `service_fee` INT NULL DEFAULT 0,
  `country` VARCHAR(64) NULL,
  `rating` DOUBLE NULL DEFAULT 3.0 COMMENT '평점\n0~5',
  `is_superhost` TINYINT NULL DEFAULT 0 COMMENT '슈퍼호스트 여부',
  `accommodates` INT NULL COMMENT '수용인원\n',
  `latitude` DOUBLE NULL COMMENT '위도',
  `longitude` DOUBLE NULL COMMENT '경도',
  PRIMARY KEY (`id`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `airbnb`.`image`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `airbnb`.`image` ;

CREATE TABLE IF NOT EXISTS `airbnb`.`image` (
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  `url` VARCHAR(64) NULL COMMENT '이미지 url',
  `listing_id` BIGINT NOT NULL,
  PRIMARY KEY (`id`, `listing_id`),
  INDEX `fk_image_listing_idx` (`listing_id` ASC) VISIBLE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `airbnb`.`user`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `airbnb`.`user` ;

CREATE TABLE IF NOT EXISTS `airbnb`.`user` (
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(64) NULL COMMENT 'github userId',
  PRIMARY KEY (`id`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `airbnb`.`booking`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `airbnb`.`booking` ;

CREATE TABLE IF NOT EXISTS `airbnb`.`booking` (
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  `checkin` DATETIME NULL,
  `checkout` DATETIME NULL,
  `adults` INT NULL,
  `children` INT NULL,
  `infants` INT NULL,
  `total_price` INT NULL COMMENT '총 결제 금액',
  `user_id` BIGINT NOT NULL,
  `listing_id` BIGINT NOT NULL,
  PRIMARY KEY (`id`, `user_id`, `listing_id`),
  INDEX `fk_booking_user1_idx` (`user_id` ASC) VISIBLE,
  INDEX `fk_booking_listing1_idx` (`listing_id` ASC) VISIBLE)
ENGINE = InnoDB;


SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

엑셀 수식

// 동일한 값일 경우 빈값으로 다를 경우에만 채우기
=IF(B2=C2,"",B2)

회고

매드포갈릭에서 맛점하고 커피 사들고 코쿼로 돌아오는 길에 날씨가 너무 좋아서 기분이 좋다. (블루보틀 라떼는 그냥 그냥..ㅎ 다음에 뉴올리언스 마셔야지)

강의듣고 점심먹고 스크럼을 끝내니 5시반이어서 운동은 포기 ㅠ 오랜만에 월화 운동했더니 너무 좋다. 될 수 있으면 자주 나가야겠다.

스프링부트와 AWS로 혼자 구현하는 웹서비스 책을 3장 까지 읽었는데 야구게임 프로젝트에서 관계형 데이터베이스를 JDBC 템플릿으로 사용하면서 느꼈던 불편했던(?) 코드들이 있었는데 어쩌면 그럴 수 밖에 없었는지도 모르겠다고 알게되었다. "객체지향 프로그래밍을 배웠는데 왜 객체지향 프로그래밍을 못하지?", "객체를 단순히 테이블에 맞추어 데이터 전달 역할만 하는 개발" <-- 내가 느꼈던 것과 같다.

이 문제의 해결책으로 JPA라는 자바 표준 ORM(Object Relational Mapping) 을 사용한다고 한다.

좀 더 공부해봐야겠다.

profile
nunnu

1개의 댓글

comment-user-thumbnail
2020년 5월 31일

크....솔라..그저..빛🎆 나도 솔라랑 같이 공부할테야

답글 달기