풀스택(Full stack) 웹 개발 후기 #3 : 서비스 개발

이 글은 혼자서 웹서비스를 만들어본 내 경험의 후기를 적은 것이다.
사실 글을 적기시작한지는 한참 전인데...
ㅋㅋㅋ 이제서야 포스팅을 완료 하게 됨;;;
이전 글들은 아래의 목차링크를 눌러 볼 수 있다.

<목차>

4. 프론트엔드 서비스 개발
5. 백엔드 서비스 개발
6. 서비스 테스트와 유지보수
7. 느낀점

이번 포스팅에서는 4, 5번을 다루고자 한다.

※ 혹시라도 제가 미숙하여 잘 모르고 적은 글이 있다면 지적 부탁드립니다.

======================================================
들어가기 전에...

아마 대부분의 서비스가 마찬가지 이겠지만, 고객들이 사용하는 프로그램이 있다면, 
관리자가 사용하는 프로그램이 따로있다. 이것은 마치 하나의 세트처럼 움직이기 마련이다.

나도 마찬가지였다. 고객용 웹 서비스가 있었고, 이것으로 유입되거나 노출시켜야 하는 데이터를 관리하는 직원용 웹 서비스 있었다. 그래서 엄격히 말해 프론트엔드+백엔드를 통합한 2개 프로젝트를 한 셈이다.

프로젝트의 진행일정은 이전 포스팅에서 적은바와 같이 딱 2달이 걸렸다.

백엔드와 프론트엔드의 개발을 극명하게 구분하는 요소가 나는 "설계의 대상" 이라고 생각한다.
그리고 그것은 아래와 같다.

백엔드의 경우 : Database, API (URL)
프론트엔드의 경우 : UI (User Interface), UX (User eXperience)

그 이외에도 신경써야할 것들은 많지만, 가장 대표적인 것들은 이렇다.


4. 프론트엔드 서비스 개발

Front-End 는 사람에 비유했을때, 외모라고 볼 수 있다.
즉, 내가만든 서비스가 최초로 사용자와 직접 상호작용하는 부분을 말한다.

그래서, 웹 서비스의 경우 주소창에 URL 을 치고 들어가면 볼수 있는 모든 화면,
게임의 경우, 사용자들이 자신의 PC 혹은 모바일에서 구동시켜 사용하는 프로그램을 일컫는다

프론트엔드에 보여지는 모든것들(텍스트, 이미지, 동영상)은 대부분 API 서버(=백엔드) 라는 것으로부터 가져온다.
클라이언트에서 자체적으로 저장하고있는 로컬 리소스도 존재하긴 하겠으나,
이것에만 의존하는 프로그램은 사실상 요즘같은 세상에는 거의 없다고 생각하면 되겠다.

프론트엔드 개발에서는 기술적인 요소 만큼, 혹은 그보다 더 중요하게 여겨지는 것이 디자인 요소이다
그래서 이와 관련하여 중요하다고 생각하는 2 가지를 적어보았다..

1. 내가 제작한 화면이 서비스의 기획이 의도한 바를 명확히 담아내었는가?
2. 내가 만든것이 사용자들 입장에서 수긍할 수 있는 것인가?

이와같은 사항들 때문에 프론트엔트 개발자들은 항상 디자이너, 기획자들과 많은 커뮤니케이션을 하고, 또 그들이 요구하는 UI, UX구현을 위해 그 많은 시간동안 삽질?을 하는 것이다.

화려한 컬러, 이펙트, 사운드도 중요하지만, 그 외에 프론트 개발자들이 더 중요하게 신경써야 하는부분이 있다.

- 어플리케이션 크래쉬 핸들링 : 에러 리포팅, 사용자에게 적절한 에러 안내 문구 OR 화면 제공
- 기기별 소프트웨어별 호환성 체크 : 요새는 하나의 앱을 여러 Device 에서 접속하여 사용하는 경우가 있다. 앱 화면이 일그러지는 경우도 있고, 간혹 기능이 제대로 동작하지 않는 경우도 발생한다. 이것에 대한 테스트 및 예외처리는 필수. 멀티 플랫폼 호환성이 좋은 오픈소스를 가져다 쓰는것도 한 방법이겟다.



5. 백엔드 서비스 개발

Back-End 는 사람에 비유했을때... 뇌(=생각)?! 라고 보면 된다.
ㅋㅋㅋ 비유가 좀 그렇긴 한데.... 백엔드는 프론트 엔드에서 사용자에게 보여줄 모든 데이터를 설계, 생성, 관리, 하며 "안정적으로" 공급하는 역할을 한다. 즉, 서비스의 실질적인 로직과 데이터를 제공하는 원천이 되는 것이다.

간혹, 백엔드가 필요없는 서비스가 있다. 즉, 어플리케이션을 설치하기만 하면 인터넷사용 가능 여부와 상관 없이 사용자가 혼자서 오프라인으로 즐길수 있는 서비스 말이다. 이런 형태의 소프트웨어는 옛날의 CD 게임이라던가,,, 오프라인 사전 이라던가.. 등등...이 있을것이다. 이런것들은 서버가 필요 없다. 하지만 근래 대부분의 서비스는 앱을 키고, 인터넷을 이용하여 매 화면마다 서버와 "통신"하여 특정 정보를 불러온다. 이러한 서비스들은 서버가 없으면 죽은 껍데기나 다름이 없는 것이다.

어떻게 생각해보면... 백엔드 프로그램은 중요한거 같기도, 안중요한것 같기도... 하다.
일단 서비스를 런칭 하기 위해서 프론트는 선택이 아닌 필수이지만 백엔드는 그렇지 않기때문에...
그리고 백엔드 서포트가 필요한 서비스의 경우, 서버가 없으면 서비스가 아예 불가능하기 떄문에...

어쩃든,, 백엔드 개발이 해야할 일들을 간단히 살펴보면 아래와 같다.
서버 종류는 다양하지만 여기서는 웹개발에 필요한 백엔드 개발을 이야기 한다.

- 데이터베이스 설계
- 서버 발주 및 세팅 = 서비스 인프라 구축
- (대량 트래픽 예상 시) 스트레스 테스트
- 데이터 load > processing > 전달 + 비즈니스 로직
- API 설계 및 개발

========================================================

내가 했던 대략적인 전체 작업 진행방식

- 세부 기획서 작성 및 필요 기능 명

- 전체 서비스 Flow 설계 및 데이터 베이스 구축

- 인증 API (= Authentication, User 관리) 개발 : 로그인, 로그아웃, 비밀번호 찾기 / 변경, 사용자 정보 추가 / 편집 / 삭제

- 서비스 화면에 따라 아래와 같은 순서로 개발 진행
1. 운영툴 페이지 UI 개발
2. 운영툴 DB Access Object 개발
3. 운영툴 페이지 기능 테스트
4. Client 페이지 UI 개발
5. Client DB Access Object 개발
6. Client 페이지 기능 테스트 
7. 운영툴 액션에 따른 Client 변경사항 반영

- 특정 기능을 담당하는 운영툴이 완료되었으면 그것의 Client 웹페이지 서비스 개발

- View 단 개발 할 때, 필요한 Ajax API 는 그때그때 추가해 나가며 개발

- 전체적으로 개발 단계에서는 프론트 엔드 쪽 화면 설계와 개발이 하나씩 진행될때마다,
   그것을 위해 필요한 Backend 개발(API, DAO 등)을  같이 진행했다.

- 디자인 시안을 프로젝트 사정 상, 좀 늦게 받아서, API 혹은 웹페이지 별로 단위테스트를 만들지는 못했다. 

기획 과 디자인 작업은 원래 프로젝트 개발에 들어가기전, 기획안 flow 에 의해 선행 되어있어야 한다.
내 경우에는 신규서비스 였기 때문에  더욱이 고객용 서비스의 주요 웹페이지(메인홈 등)만 전문 디자이너로부터 직접 화면 시안과 리소스를 받아 디자인을 하였다.
그래서 중간에 계속 시안이 변경되고.. 나는 또 계속 업데이트 하고.. 참... 작업 자체가 번거로웠다기 보다는 정신적으로 힘들었던것 같다;;ㅋㅋ
나 같은 경우에는 백엔드 개발 시, Front 개발을 같이 병행하며 개발을 진행해 나갔지만, 근래에는 웹 프론트 기술이 좋아져서 백엔드코드를 프로젝트에서 온전히 독립적으로 가져가 API 형태로만 제공하고 이를 호출하여 서비스 UI에만 집중하는 프론트 엔드 프로젝트를 따로 개발할 수도 있다.
개인적으로는 백엔드와 프론트 엔드 코드를 확실하게 분리하여 가져가는법도 코드의 유지보수성에 있어서 나쁘지 않은 방법이라고 생각함...


[Sourcetree Tip] 원격 레파지토리 인증정보 갱신하기 (Update Remote Authentication information) 개발 이것저것

Sourcetree 에서 아래와 같은 에러를 만나신 분에게 !!
도움이 되는 해결책 입니다. ㅎ

invalid username or password

이게 저도 구글링을 몇번 해봤는데.. 제 소스트리 버전에 맞는 정보가 아니고 다 옛날UI 기반으로 설명을 하고 있더라고요...

여튼... 일단 아래와 같이 인증정보를 편집할 수 있는 설정 화면으로 이동하시면 됩니다.


<in Eng>
Sourcetree > Preference > Advanced tab 

<in Kor>
Sourcetree > 설정 > 고급

여기가시면 아래쪽에
호스트명 & 사용자명 테이블이 있을겁니다.

요기에서 갱신하고자 하는 인증정보를 날리고 !!!
다시 fetch pull, push... 어떤거든 시도하시게 되면 다시 ID, PW 를 입력하라고 할겁니다. ㅎㅎ


끝 !

[MySQL] 여러개 프로세스 한꺼번에 죽이기 (Kill multiple process) MySQL

Too many connections ...

가끔 
잘못 코딩된 (DB 커넥션 관리를 안하는) 프로그램이 있다거나...
그냥 그저 커넥션 수요가 많은 DB 이거나... 할경우
저 에러가 나면서 DB접속을 못하는 경우가 있다.

이 에러를 겪게 되면 해당 MySQL 서버에 한번 날려보는 쿼리가 있다.
show processlist

현재 해당 MySQL 서버가 맺고있는 커넥션들을 모두볼수 있다.
그때 User, Host, db 등의 필드 정보를 볼수 있는데,
이를 바탕으로 대충 어떤 프로그램이 or 사람이 커넥션을 많이 사용하는지 유추할 수 있다.

가장 좋은 방법은 원인 프로그램이나 사람을 찾아서 커넥션을 끊도록 하는건데...
아래와 같은 방식으로 가능하다.

===========================================================

- IP로 프로세스 찾아내기
select * from information_schema.processlist where host LIKE '172.28.81.105%';

- 특정 IP 프로세스의 KILL 쿼리 string들 뽑아내기
select concat('KILL ',id,';') from information_schema.processlist where host LIKE '172.28.81.105%';

- user 로 프로세스 찾아내기
select concat('KILL ',id,';') from information_schema.processlist where user='root';

===========================================================

뽑아낸 KILL 쿼리 모습

+------------------------+
| concat('KILL ',id,';') |
+------------------------+
| KILL 3101; |
| KILL 2946; |
+------------------------+
2 rows in set (0.00 sec)

===========================================================

- 만들어진 KILL 쿼리 스트링을 파일로 뽑아내기
select concat('KILL ',id,';') from information_schema.processlist where user='root' into outfile '/tmp/a.txt';


- KILL 쿼리들을 불러와서 실행시키기
source /tmp/a.txt;


[디버깅로그] branch diverged 해결 + git 브랜치 롤백 + master 갈아치우기 개발 삽질이야기

가끔... 실서버에 배포된 master 코드가 오류를 많이 발생하여 rollback 하게되는 경우가 있다.

먼저, 브랜치 롤백을 하는 방법은 크게 아래의 2가지 정도를 생각해볼 수 있다.

1. 이전 릴리즈 태그에서 체크아웃 한 다음, 롤백용 브랜치를 만들어 배포
2. 마스터 브랜치에서 잘못된 이전 커밋만 revert하여 배포

자,, 나는 실제 상황에서 1번 해결법을 선택하였다.
그 이유는 이미 작업이 진행중인 다음버전의 추후 Merge 시, revert 했을때 사라지는 코드들에 대한 merge conflict 해결하는것이 귀찮아서였다.
음.. 쉽게 말하자면... 예를 들어야겟지..?

<예시 ... 상황설명>
이전 stable master 버전이 1.1 이라고 하자.
그리고 이번에 배포되었는데 문제를 일으키고 있어 롤백이 필요한 버전이 1.2 라고 하자.

이떄, 이미 1.3 버전에 나가야 하는 feature 브랜치들 중 일부가 이미 1.2 버전의 코드들을 포함하고 있다고 생각해보자.
그렇다면 1.2 버전의 master 브랜치에서 일부 과거 커밋에 대해 revert 커밋 (= 코드삭제) 이 되었을때,
추후 1.3 브랜치로 merge 가 이루어 지면, 삭제 코드들을 다시 채워넣어야 하는 상황이 생긴다.


=================================================

Anyway....
결국 롤백 브랜치 만들어서 그걸로 일단 배포를 해서 리얼은 안정화를 했는데....
나중이 문제다..

계륵과같은 상황(쓰기도 뭐하고 버리기도 뭐한...)에 놓인 마스터를 어떻게 처리할 것인가?
일단 master 브랜치는 속성상 항상 리얼서버에 배포된 코드와 동기화 되어있어야 하므로.. 그걸 맞춰줘야한다.
그래서... 아래와 같이 처리를 진행하였다.

1. 오류난 버전 1.2 에서 정상코드만을 추려낸 1.2.1 브랜치를 만들기

   - 롤백 브랜치에서 QA 용으로 1.2.1 브랜치를 만든다.
   - 해당 브랜치에서 버전 1.2 에 반영되려 했던 코드들 중 문제가 발생한 커밋만을 제외하고 나머지 커밋을 모두 체리픽 한다.
     (또는!!! 만약 1.2 버전의 기능별 feature 브랜치가 아직 살아있다면, 배포 후 오류가 없던 feature 브랜치만 다시 merge 한다)

2. Repository master 교체하기

   - git repository setting 에서 master branch 의 protected 해제
   - remote origin/master branch 삭제
   - 현재 리얼과 동일한 해쉬를 가진 롤백브랜치에서 master 로 브랜치 아웃 & 푸시

3. 각 서비스 서버에서 master 브랜치 갱신해주기

   - 앱이 동작하는 서버에서 git fetch, git pull 을 하게되면 branch diverged 가 뜨면서 에러가 날 것이다.
   - 이는 기존의 서버가 알고있던 master branch 가 아예 새로작성되었기 때문에 발생하는 오류인데 이때는 아래와 같이 해야한다.
   - 다른 임시 브랜치로 갈아탄다
   - git branch -D master (master 삭제)
   - git fetch --all  (remote 브랜치 정보 모두 가져오기)
   - git checkout master (다시 마스터 브랜치로 갈아타기)

=================================================

뭐... 주저리 주저리 하다보니좀 길어졌는데...
그냥 사실 내가 한 일을 간단히 요약하면 아래와 같다.

삽질했다.

.
.
.
는 아니고...

1. 새로운 버전을 배포했다.

2. 문제가 생겨서 롤백했다.

3. master 를 롤백한 브랜치로 갈아치웠다.

얼핏 봐서는, 디버깅로그를 굳이 남길 필요가 있나 싶지만...
3번 step 에서 리얼 서비스 서버의 master 를 제대로 교체해주지 않으면
이후에 master 브랜치 배포때마다 에러가 나기때문에... 주의가 필요하다.

필자의 경우는 에러가 났는데 젠킨스가 (배포스크립트를 잘못짜서...) 정상배포 됬다고
뻥(?)을쳐는 바람에 결국 과거의 잘못된 master가 또다시 리얼로 등장하게되고....
나도 하필 퇴근하다가 다시 회사로 등장?하게되고...
야근 하게되고... ㅋㅋㅋ

여튼 그렇게 어처구니 없는 사고가 발생했었다.

그래서... 지금은 배포스크립트도 제대로 고쳐놨고...
버그도 고쳤고... 했으니 ...
이젠 괜찮겟지...? ㅋㅋㅋ



[Python] unpacking_operator (=*) 와 그 사용법 (positional_argument, keyword_argument) Python

이 글은 python 에서 사용되는 일종의 자료형(?)에 속하는 
positional_argument 와  keyword_argument 에 대한 설명입니다. 

일단 각각의 개념정의와 용법을 알아봅시다.

1. unpacking operator (=*)

파이썬의 list 타입 변수와 dict 타입 변수를 함수 인자값으로 활용하기 위해 사용되는 연산자 입니다.
아래에서 예제까지 들어 확실하게 이해를 돕겟지만, 가령 아래와 같이 생각하시면 됩니다.
--------------------------------------
리스트의 경우

a = [1, 2, 3] 가 있다면,
*a 는 함수 인자값으로 1, 2, 3 이 됩니다.
괄호가 벗겨지게 되죠 ㅎㅎ
--------------------------------------
Dictionary 의 경우는 그럼 어떨까요?

d = {'a':1, 'b':2} 가 있다면
**d 의 경우 a=1, b=2 와 같이 변합니다.

자, 그럼 각각의 설명과 예제를 통해 하나씩 보시죠


2. Positional arguments (=args)

직역하면 위치(순서)를 가진 인자값들 이 됩니다.
즉, 순서를 가진 연속적인 복수개의 단일 입력값 을 지칭하고요.
함수 argument 들의 선언순서에 따라 입력값을 한번에 집어넣고자 할때 쓰입니다.

아래 예제를 한번 보시죠.


def mysum(a, b):
return a + b

tmp_list = [2, 6]
result = mysum(*tmp_list)
print(result) # 8

여기서 *tmp_list 에 주목하실 필요가 있습니다.
분명히 리스트에 들어있던 2, 6 값이 각각 mysum 함수의 a 와 b 에 각각 맵핑되었죠?
이렇게 함수 순차 인자값으로 리스트에 있던 element 들을 한방에 활용이 가능합니다.


3. Keyword arguments (=kwargs)

파이썬 함수는 argument 의 key를 직접 지정할 수 있습니다.
그래서 kwargs 같은 경우에는, 키워드별 인자값들 이라는 직역처럼,
Key 와 Value 지정이 가능한 함수 argument 의 input 을 한번에 집어넣고자 할때 쓰입니다.

아래 예제를 한번 보시죠.


def mycalc(a=1, b=2, c=3):
return a + b - c

mydic = {'a': 10, 'c': 8}
print(mycalc(**mydic)) # 10 + 2 - 8 = 4

mydic2 = {'a': 4, 'b': 7, 'c': 6}
print(mycalc(**mydic2)) # 4 + 7 - 6 = 5

인자값들을 mydic 이라는 dict() 형 변수에 다 담은뒤,
변수앞에 ** 을 붙여서 한방에 함수로 넘기는것을 보실 수 있습니다.



참고했던 링크입니다~ ㅎ 궁금하신분은 한번 보셔요!
https://stackoverflow.com/questions/7527849/how-to-extract-parameters-from-a-list-and-pass-them-to-a-function-call



1 2 3 4 5 6 7 8 9 10 다음


통계 위젯 (블랙)

27174
1010
137470

GoogleAdsenseResponsive

Cluster map