참고 URL 하나로 시작한 첫 프로젝트
첫 회사, 수습 3개월 때 받은 첫 프로젝트 기록. 지금 보면 삽질 덩어리인데 그래서 더 남겨둠.
참고 URL 하나가 요구사항의 전부
회사가 새로 밀던 사업이 하나 있었음. 이게 생각보다 잘돼서, 사업자한테 쇼핑몰을 만들어주고, 그 사업자의 고객을 위한 기능까지 넣어주는 프로젝트였음. 말하자면 B2B2C.
문제는 정보가 아무것도 없었다는 거. 기획서도, 화면 정의서도 없고 참고할 만한 사이트 URL 하나 딱 던져주고 “이거 보고 해줘” 로 끝.
그래서 뭐지 하면서 그 사이트 뜯어봤음. 어떤 기능 있는지 조사하고, 모방하고, 기획서를 만들기 시작함. 그러다 부장님이 “기획서 필요 없고 그냥 참고 사이트 보고 만들어” 하셔서 기획서는 중단하고 바로 개발 들어감.
템플릿이 없었다
그전까지 회사 다니면서는 회사마다 템플릿이 있어서 그거 복사해서 시작했는데, 여긴 그게 없었음. 정확히는 그누보드 4~5는 쓰고 있었는데, 부장님이 “우리도 이제 CI3로 만들어보자” 하셔서 그누보드는 접음.
CI3를 쌩으로 처음부터 짜는 건 부담이라, 관리자 페이지랑 쇼핑몰이 어느 정도 갖춰진 CIboard 오픈소스를 베이스로 잡음. 로컬에서 API랑 관리자 페이지 얼추 셋팅해서 굴러가는 것까지 확인함.
아파치마다 PHP 버전이 고정돼 있었다
로컬에서 다 되는 걸 서버에 올리려는데 여기서 막힘.
서버 구조가 좀 특이했음. 아파치 인스턴스를 여러 개(아파치2, 아파치3…) 띄워두고, 아파치마다 물려 있는 PHP 버전이 달랐음. 그때 깔려 있던 건 PHP 5.2랑 5.3 두 개.
- 홈페이지가 물려 있던 아파치가 PHP 5.2.17 — CI3 공식 문서가 이 버전대는 지원 안 하니 쓰지 말라고 해서 CI2로 감
- git 설치도 안 돼 있음
지금 생각하면 답은 뻔함. 아파치를 하나 더(아파치4) 올려서 최신 PHP를 물리고, 홈페이지를 거기로 붙이면 되는 거였음. 근데 그땐 “기존 서버 환경에 맞춰야 한다”는 생각에 갇혀서 반대로 감. CIboard에서 문제 되는 코드를 직접 다 찾아서 덜어내고 CI2로 다운그레이드, PHP 문법도 5.2에 맞춰서 다 손봄.
// 최신 PHP 문법 → PHP 5.2에서 되는 문법으로
[] → array() // 단축 배열은 5.4부터
$a ?? $b → isset($a) ? $a : $b // 널 병합(??)은 7.0부터
이런 걸 코드 전체에서 찾아 바꿈. 프레임워크를 서버에 맞춘 게 아니라 서버 때문에 프레임워크를 뜯은 셈.
프론트 Vue2 로 작업
프론트 개발자가 있다고 했는데 알고 보니 퍼블리셔였음. 결국 퍼블리싱만 다 돼 있는 화면에 내가 직접 동작을 붙여야 했음.
jQuery ajax로 다 짜기는 싫어서 Vue2를 CDN으로 import 하는 방식으로 감. 빌드 세팅 없이, 페이지마다 new Vue 하나씩 띄우는 구조.
<script type="module">
import { myAjax, dateYmd } from '/config/config.js?v=<?=date('ymdhis')?>'
new Vue({
el: '#app',
data() {
return {
is_loaded: false,
chk: [],
chkall: false,
list: [],
totalCount: 0,
page: 1,
pageSize: 10,
sfield: 'member_id',
skeyword: '',
}
},
created() {
this.init()
},
methods: {
async init() {
const isLogin = await this.autoLogin()
if (!isLogin) return
this.is_loaded = true
this.getList()
},
search() {
this.page = 1
this.getList()
},
async del() {
if (this.chk.length === 0) return
const confirm = await Swal.fire({
html: `총 ${this.chk.length}개 삭제하시겠습니까?<br/>삭제 시 복구 불가.`,
icon: 'warning',
showCancelButton: true,
})
if (!confirm.value) return
const res = await myAjax(this.API_URL + '/admin/member/del', { chk: this.chk })
if (res.code !== 200) {
await Swal.fire({ html: res.message, icon: 'error' })
return
}
await Swal.fire({ html: res.message, icon: 'success' })
this.chk = []
this.chkall = false
this.init()
},
},
})
</script>
화면 목록도 퍼블리싱된 마크업 위에 v-for만 얹는 식으로 처리함.
<ul class="prd-list">
<li v-for="(irow, i) in items.order_parts_list">
<div class="prd-info">
<a :href="`/app/parts/view?idx=${irow.parts_idx}`">
<img :src="irow.file_url" :alt="irow.file_name" style="width:60px;height:60px;" />
</a>
<a :href="`/app/parts/view?idx=${irow.parts_idx}`">{{ irow.parts_name }}</a>
</div>
<div class="prd-price">
<div><span>수량 :</span> {{ addCommas(irow.parts_count) }} 개</div>
<div><span>판매가 :</span> {{ addCommas(irow.parts_price) }} 원</div>
<div class="prd-total">
<span>소계 :</span>
<strong>{{ addCommas(irow.parts_count * irow.parts_price) }} 원</strong>
</div>
</div>
</li>
</ul>
CI2 라우팅으로 API 디렉토리 정리
하다 보니 CI2는 controller/adm/api/member.php 처럼 컨트롤러를 여러 겹 디렉토리로 두는 걸 지원 안 했음. 그래서 관리자 API를 admin_api 한 디렉토리로 합치고, 라우터로 경로를 매핑해서 씀.
$route['api/admin/(:any)'] = '_api_admin/$1'; // 관리자 API
URL은 계층 구조처럼 보이게 두되, 실제 컨트롤러는 한 폴더에 몰아넣는 방식으로 타협함.
발표, 그리고 버려짐
그렇게 2~3개월 붙잡았고, 수습 3개월 끝날 때 이걸로 발표까지 함.
근데 추후에 알게 된 결말이 있음. 막상 만들어서 고객한테 줘봤더니 —
- 불편하다
- 다들 보통 휴대폰으로 보는데 모바일에서 보기 불편하다
- 등록할 게 너무 많다
그래서 안 쓰신다고 함. 결국 특정 기능 몇 개만 관리자들이 쓰고, 프로젝트 자체는 버려졌음.
남은 것
남은 교훈은 명확함.
- 환경을 코드에 맞추면 되는 걸, 코드를 환경에 맞춰서 뜯었다. 아파치 하나 새로 올려서(아파치4) 최신 PHP 물리면 끝날 일을, CI3 → CI2 다운그레이드 + 5.2 문법 맞추기로 몇 배 더 고생함. “기존 환경 유지”가 항상 정답은 아님.
- 담당자가 있어도 현장을 모르면 없는 거나 마찬가지. 프로젝트 담당자는 따로 있었는데 그분도 현장을 몰랐음. 그럼 개발자인 내가 먼저 “이 기능 실제로 쓰는 사람한테 필요한 거 맞냐”부터 적극적으로 캐물었어야 했는데, 시키는 대로 화면만 채웠음. 요구사항은 위에서 내려주길 기다릴 게 아니라 내가 먼저 파고들었어야 했음.