오늘 한일

플러터 1/4/7/14 앱: 메인화면

원래 계획은 in-memory db 적용이었으나, 우선은 db없이 컬렉션으로만 적용해봤다.

class SubjectRepository {
  static List<Subject> _subjects = [
    Subject.temp(1, '컴퓨터 구조', Colors.blue.value, [SubjectHistory(DateTime.parse('2019-03-10 12:10'))], 0),
    Subject.temp(2, '알고리즘', Colors.green.value, [SubjectHistory(DateTime.parse('2019-02-10 12:10'))], 1),
    Subject.temp(3, '자료구조', Colors.purple.value, [SubjectHistory(DateTime.parse('2019-01-10 12:10'))], 2),
    Subject.temp(4, 'subject', Colors.blue.value, [SubjectHistory(DateTime.parse('2018-12-10 12:10'))], 3),
    Subject.temp(5, 'subject2', Colors.blue.value, [SubjectHistory(DateTime.parse('2018-11-10 12:10'))], 4),
    Subject.temp(6, 'subject3', Colors.blue.value, [SubjectHistory(DateTime.parse('2018-10-10 12:10'))], 5),
    Subject.temp(7, 'subject4', Colors.blue.value, [SubjectHistory(DateTime.parse('2018-09-10 12:10'))], 6),
  ];
  static List<Subject> findAll() {
    List<Subject> result = List<Subject>.from(_subjects);
    result.sort((sub1, sub2) => sub1.pos - sub2.pos);
    return result;
  }

  static void save(Subject subject) {
    var index = _subjects.indexWhere((el) => el.key == subject.key);
    _subjects[index] = subject;
  }
}

class _SubjectSizedCardsState extends State<SubjectSizedCards> {

  final List<SubjectSizedCard> _cards;

  _SubjectSizedCardsState(this._cards);

  
  Widget build(BuildContext context) {
    void _onReorder(int oldIndex, int newIndex) {
      setState(() {
        SubjectSizedCard row = _cards.removeAt(oldIndex);
        _cards.insert(newIndex, row);

        _updatePositions();
        SubjectService.saveAll(_cards.map((card) => card.subject).toList());
      });
    }

    return Expanded(
      child: ReorderableWrap(
        children: _cards,
        onReorder: _onReorder,
        maxMainAxisCount: 2,
      ),
    );
  }
    
 void _updatePositions() {
    setState(() {
      for (var i = 0; i < _cards.length; i++) {
        _cards[i].subject.pos = i;
      }
    });
  }
}

일단, 패키지 위젯에서 제공하는 샘플의 reorder 기능이 removeAt과 insert를 이용한 삭제/재삽입을 통해 이루어지기 때문에 과목들의 position을 update하고 저장하는 구조로 구현했다.

자체 정렬 기능을 가진 컬렉션과 함께 vue-trello 에서 구현했던 방식을 사용하면 부하를 줄일 수 있을 것 같다. 과목 순서 변경이 크게 부하를 줄 것 같지는 않다만....

IT인프라

  • 수평 분할형 아키텍처
    • 용도가 같은 서버를 늘려가는 방식으로 확장성이 향상됨
    • 대수가 늘어날수록 안정성이 높아지며 성능 향상도 실현할 수 있음
    • 단순 수평 분할형 아키텍처
      • 같은 기능을 가진 복수의 독립적 시스템으로 단순 분할 (sharding, partitiong)
      • 지리적으로 멀리 떨어진 시스템에 자주 사용
      • 데이터 일원하 불가, 복수의 시스템 업데이트, 적절한 처리량 분배 필요
    • 공유형 아키텍처
      • 일부 계층에서 상호 접속이 이루어지는 방식
      • 예: 오라클 DB의 클러스터 기능은 어떤 DB 서버에 접속해도 같은 결과를 반환하도록 내부적으로 데이터를 교환
      • 독립성과 공유한 계층의 확장성이 낮아짐
    • 지리 분할형 아키텍처
      • 업무 연속성, 시스템 가용성을 높이기 위해 지리적으로 분할
      • 스탠바이형 아키텍처 (액티브-스탠바이)
        • 물리 서버가 최소 두 대이며 하나가 고장나면 소프트웨어를 다른 한 쪽으로 옮겨서 실행
          • 페일오버: 소프트웨어를 자동으로 재시작
        • 보통 때는 스탠바이가 놀고 있는 상태가 되기 때문에 리소스 측면에서 낭비가 발생
      • 재해 대책형 아키텍처
        • 재해를 대비한 아키텍처 구성
        • 예: 두 개의 데이터 센터를 두어 상용 환경에서 고장이 발생하면 다른 환경에서 업무 처리를 재개
        • 상용 환경과 예비 환경이 동일해야 함
        • 데이터 동기화 문제
      • 클라우드형 아키텍처
        • 3계층형 시스템의 일부 또는 전부를 클라우드 서비스로 제공

리팩토링

  • 추상화 악취 2가지 복습
    • 불필요한 추상화
    • 미활용 추상화
  • 중복된 추상화
    • 동일한 이름 혹은 동일하거나 유사한 구현이 있는 경우
    • DRY(Don't Repeat Yourself) 원칙: 위반
    • copy&paste, 주먹구구식 유지보수 등을 통해 생성됨
    • 유일하게 만드는 리팩토링을 적용
    • 동기화 관련 (ArrayList, Vector), DDD에서의 이름 중복 등은 허용 가능
  • 캡슐화
    • 추상화의 구현 세부 사항과 변경 가능성을 감추는 기법
    • 관심사의 분리와 정보 은닉을 옹호
    • 부족한 캡슐화
      • 추상화 내부에 선언된 접근 가능성이 필요보다 관대한 경우
      • 모든 추상화에 접근 가능한 전역 상태가 있는 경우(전역 변수, 전역 자료 구조 등)
      • 예: 필드를 public으로 선언한 경우
      • private은 구현 세부 사항
        • private 메소드를 테스트 하는 경우 리플렉션을 사용하는 것을 추천
      • public이 반드시 성능이 좋다고 고집하지 말기를...
        • 최산 컴파일러와 JIT 컴파일러는 getter/setter를 인라인으로 처리

운영체제

  • day1, day4, day6 복습
    • day1: 컴퓨터 하드웨어의 구성, 컴퓨터 시스템의 동작
    • day4: 프로세스의 개념과 상태 변화, 프로세스 관리(구조, 생성, 삭제 등)
    • day6: 병행 프로세스 (독립 프로세스, 협력 프로세스), 선형 그래프, 병행 프로그램
  • day7 학습
    • 상호배제
      • 병행 프로세스에서 프로세스 하나가 공유 자원을 사용할 때, 다른 프로세스들이 동일한 일을 할 수 없도록 하는 방법
      • 동기화
        • 공유 자원을 동시에 사용하지 못하게 실행을 제어하는 방법
        • 동기화로 상호배제를 보장할 수 있음
        • 교착 상태, 기아 상태가 발생할 수 있음
    • 임계 자원
      • 두 프로세스가 동시에 사용할 수 없는 공유 자원
    • 임계 영역
      • 임계 자원에 접근하고 실행하는 프로그램 코드 부분
      • 프로세스가 공유 데이터에 접근할 때 임계 영역에 있다고 표현
      • 다수의 프로세스가 접근할 수 있지만, 어느 한 순간에는 반드시 하나의 프로세스만 사용 가능
      • 상호배제, 동시 진입 요청의 적절한 처리, 무한정 대기 X 등을 만족해야 한다.
    • 생산자/소비자 프로세스
      • 운영체제에서 비동기적으로 수행하는 모델
      • 생산자와 소비자가 불필요하게 공회전하지 않도록 데이터를 전송하기 위해 버퍼를 사용
      • 공유 버퍼가 가득 차거나 비어있는 경우를 고려해야 함
        • 무한 버퍼에서의 독립적 알고리즘 수행, 유한 버퍼에서의 순환 배열 구현
      • 프로세스들이 접근 순서에 따라 실행 결과가 달라지는 경쟁 상태가 될 수 있음
        • 적절한 순서의 실행과 동기화가 필요
        • 동기화는 임계 영역을 이용한 상호배제로 구현할 수 있음

백준 DP: 가장 긴 바이토닉 부분 수열, 연속합

가장 긴 바이토닉 부분 수열은 이전 문제들의 응용 문제라고 생각해서 풀이를 올렸다. 연속합은 뭔가 어려워보였는데, 두 가지 케이스밖에 없는 것을 이용해서 문제없이 풀 수 있었다.

오늘 느낀점

앱 개발이 처음이다 보니 완전 주먹구구식으로 개발 중이다. 처음 접하는 언어라 낯설기도 하고 개발 속도가 잘 안나온다. 자꾸 뭣도 모르면서 테스트를 작성하려다 보니까 더 그런 느낌이 든다. 테스트에 집착하지 말고 우선 1.0 버전까지 완성하고 유닛 테스트를 작성해보는 것도 좋을 것 같다.

내일 할일

  • 플러터 1/4/7/14 앱: 메인화면 개발
    • in-memory db 적용해보기
    • 과목 추가 기능 개발
    • 과목명 필터링 기능 개발
  • IT인프라, 리팩토링, 운영체제 학습
  • 백준 DP 2문제 풀이