소스 없는 ASP.NET 코드 수정하기

Posted at 2008/08/31 12:21// Posted in dev
이 포스트는 논픽션 코딩 스릴러삽질러임.


눈누난나_ 즐거운 퇴근길이다. 계절이 가을로 넘어가려는 여름이라 그런지, 7시 퇴근을 하면 슬슬 어둑어둑해진다. 오늘도 어김없이 이어폰을 꼽고 사람들 사이로 휘리릭리 지나간다. 지하철역에 도착할 때 쯔음 지하철이 바로 왔기 때문에 환승 최적 포인트인 앞자리까지 안가고 적당히 앞쪽에서 그냥 탔다. Lucky~ 자리가 있어서 냉콤 앉아서 꾸벅꾸벅 졸면서 가기 시작한다.

얼마쯤 갔을까 갑자기 진동이 울린다. 뭔가 해서 보니 전화가 오고 있다. 영자님이다. '아, 서버 장애가 났나보다. 난 지금 지하철로 집에 가는중인데' 하면서 전화를 받는다.

  "여보세요"
  "제루씨, 난데"
  "응"
  "지금, 게시판이 안된데"
  "응?"

이건 뭥미? 갑자기 게시판이 왜 안되지 하는 생각과 함께 스쳐지나간 오늘 오후의 업데이트. 분명, 웹 취약점 분석 리포트를 받고 그 중 한 부분에 대해서 패치를 했었다. 하지만, 그건 첨부파일 확장자 검사를 해서 허용하지 않는 파일에 대해서만 클라이언트 스크립트로 alert 뿌려주고 종료하는 내용의 패치인데? 게다가 기본적인 글쓰기는 테스트를 했었다.

  "모든 게시판이 다 안되는거야?"
  "아니, ㅇㅇ게시판에 글쓰기하면 오류가 난데"
  "음.. 나 지금 집에가는 중인데, 집에가서 보게 되면 1시간정도 걸릴꺼야"
  "그럼, 장애 공지 띄워야겠네?"

아.. 하지만 할 수 없지.

  "응. 할 수 없지. 집에가서 해결하면 연락줄께"
  "알았어~"

끊고 나니 머리 속에 오만가지 생각이 다 떠오른다. 어디가 잘못된걸까, 어떻게 고치지, 회사로 돌아갈꺼 그랬나 등등. 하지만, 회사로 돌아가기는 싫다. -_-;; 집에서 VPN으로 접속해서 수정하면 되겠지. 되겠지.. 응?

생각해보니 ASP.NET으로 되어있는 우리 사이트를 수정하려면 소스가 필요한데, 소스는 전부 회사 내 PC에 있다. 그리고 내가 사용하는 VPN은 분명 IDC 내에만 들어갈 수 있고, 내 PC로 들어가는 VPN이 아니다. 결국, 소스 없는 상태에서 수정을 할 수 있을까라는 문제에 봉착한 것이다. 그게 되지 않으면 결국 회사로 다시 출근해야 하니까. 순간, 그깟 게시판 12시간 안된다고 뭐 이상하겠어 라는 생각까지 떠오른다. 나도 참 막장인가보다.

하지만 닷넷이기에, 우리의 Reflector가 있기 때문에 바로 생각을 접었다. 서비스 서버에서 aspx페이지하고 어셈블리(DLL)파일 내려받아서 디어셈블해서 보고, 해당 클래스만 신규 어셈블리로 만들어서 aspx페이지를 그 어셈블리로 연결하면 되겠지. Page 지시자에 있는 Inherits 부분이 가르키는 클래스 명만 수정하면 될꺼야. 끄덕끄덕

  나.. 참 잔머리 꾼이구나.

더 이상의 쓸떼없는 생각은 접고, 체력 비축(?)을 위해서 꾸벅꾸벅 졸면서 집에 왔다. 집에 오자마자 가방부터 던져놓고, 바로 컴퓨터를 켰다. 노트북에는 개발환경이 다 꾸며져있을텐데, 동생이 빌려가서 그냥 집에있는 데탑을 켰다. 부아아아앙

일단, 오류로그를 보기로 했다. 이벤트 로그에 Exception에 대한 로깅을 하기 때문에 ㅇㅇ게시판에서 글쓰기를 냉콤 해보았다. 사진을 올리는 게시판이라서 적절한 짤방을 첨부하여 글쓰기를 꾸욱 눌러줬다. 잠시 후 오류페이지로 넘어가면서 죄송하단다. 내가 만든 오류페이지를 내가 보려니 이상야릇한 이 기분. 어쨌든 오류 로그를 보기로 한거였으니 실서버에 접속해서 이벤트 로그를 찾아본다.

  (뒤적뒤적)

차..찾았다! 가 아니고.. 찾았지만 거참 null reference exception이라면서 정확한 Stack Trace가 안나온다. 아무래도 COM+흉내낸다면서 ContextAttribute 사용해서 Auto Commit을 구현해놨더니 ContextBoundObject를 상속받은 부분부터는 안나온다. -ㅅ-;; (참고 : Declarative Transactions using ADO.NET w/o Enterprise Services via CodeProject) 에잉대잉. 그냥 코드나 봐야겠다.

다시 실서버 접속해서 사용중인 어셈블리와 aspx 페이지 파일들을 받는다. 오늘 오후에 확장자 검사하는 패치 부분이 제일 의심이 가므로 그 부분을 집중적으로 살펴보아야겠다. 4개 가량의 dll과 2개의 aspx파일을 받았다. 그리고 간략히 개발환경을 구축하자. 아직까지 닷넷 1.1을 사용하고 있어서 .NET Framework Version 1.1 Redistributable Package를 받는다. 컴파일은 csc.exe 도구를 사용할 것이기 때문에 이정도로 충분하다. 코딩툴은 아무래도 메모장은 불편하므로, 기존에 깔려있던 EditPlus를 사용하기로 했다. 디어셈블러는 위에 써 두었던 Reflector의 최신버전을 받았다. 부릉부릉. 이제 시작해볼까!

Refector를 이용해서 오늘 패치한 부분들의 코드를 점검한다. 여러 게시판들에 전부 CCV 방법론을 적용해서 패치한건데 왜 문제가 있을까.....도 아니잖아; 여튼 조심스럽게 하나둘씩 찾아보니 역시나 일반 게시판과 사진 게시판을 구분하지 않고 패치한게 문제였다.

일반 게시판의 경우
entity.AttachFile = Request.Files["AttachFile"];
if (!FileUtil.IsAllowExtension(entity.AttachFile))
{
    // 안됩니다
}

이러한 코드 때문에 정상적으로 잘 되는데, 사진 게시판의 경우 같은 엔티티 객체의 다른 속성을 사용하기 때문에 문제가 되었던 것이다.

entity.PhotoFile = Request.Files["AttachFile"];
if (!FileUtil.IsAllowExtension(entity.AttachFile))
{
   // 안됩니다
}

초보 중의 上초보 실수에다가, 이런 부분들이 검증이 안되고 넘어갔다는 점은 부끄럽기 서울역 거지 없지만 지금은 어쨌든 장애를 해결하는게 최우선 과제이다.

먼저, Reflector를 이용해서 해당 클래스 부분의 C#코드만 전부 추출 한다. 추출을 하게 되면 컴파일러에서 약간의 최적화를 한 코드를 추출할 수 있는데, 이 최적화라는 부분이 우리가 생각하는 코드레벨의 최적화가 아니라 각종 enum 값의 치환, getter/setter의 컴파일된 메소드 직접 호출 부분이라서 이 코드를 다시 붙여넣고 컴파일한다고 바로 컴파일이 되지 않는다. 하기 코드에 간단한 예시를 들어본다.

enum Hamburger
{
    BigMac = 1, Wapper = 2, TowerBurger = 3
}

// 이런 코드가 있다고 하면
zeru.Eat(Hamburger.BigMac);

// 이런식으로 나온다
zeru.Eat(1);

이러한 부분들을 찾아서 바꿔주고, 각종 using문은 당연히 코드레벨에만 있고 어셈블리 레벨에는 없을 것이므로 이부분도 잘 유추해서 코드에 적어주어야 한다. 그리고, 가장 중요한 버그 패치한 코드를 넣어준다.

대충 코드 수정이 다 되었으니, namespace를 동일하게 두고 class명만 살짝 바꿔준다. 이 바꿔준 클래스명으로 aspx페이지의 코드비하인드를 연결하도록 Page 지시자를 수정해주면 일단 작업 끝.

using System;
....
using Company.Product.Domain.BizLogic;

namespace Company.Product.Domain.Web.Community.OOBoard
{
    public class Write_modifed : BasePage
    {
        ....

        private void Write()
        {
            ....

            entity.PhotoFile = Request.Files["AttachFile"];
            if (!FileUtil.IsAllowExtension(entity.PhotoFile))
            {
                // 안됩니다
            }

            ....
        }
    }
}

우왕ㅋ굳ㅋ

<%@ Page language="c#" Codebehind="Write.aspx.cs" AutoEventWireup="false" Inherits="Company.Product.Domain.Web.Community.OOBoard.Write_modified" %>

이제, dll도 슬그리둥둥 컴파일을 하면 된다.

d:\work>csc /r:Company.Product.Framework.dll;Company.Product.Board.dll /t:library *.cs

이래서 나온 결과물들을 그대로 실서버에 적용한다. 역시나 혹시 모를 예외상황에 대비해서 기존 파일들은 백업 받도록 한다. 닷넷 배포의 가장 장점은 역시나 xcopy 배포가 가능한 점일 것 같다. 게다가 평소에 귀찮아서 코드 난독화도 안하고 있으니 이런식으로 소스 없어도 뜯어 고치기가 가능한거 아닌가. 아, 이건 장점이 아닌가?

전부 적용후에 다시 ㅇㅇ게시판으로 들어가 글쓰기를 테스트해본다. 잘 된다.

  휴우

전부 상황종료 되었다. 이제, 노심초사하고 있을 영자님에게 알려줘야지. 그리고 이런 장애가 안나게, 그리고 더욱 수월하게 - 오늘처럼 꽁수가 아니게 - 해결하기 위해서 몇가지 장치를 해두어야 할 것 같다. 내PC에 접근 가능하게 VPN신청을 좀 해두던가, svn서버를 IDC로 이전한다던가 해야겠다. CCV 방법론 적용할 때 먼저 눈으로 한 번이라도 더 봐야겠고.. 가능하면 Build Script에 단위 테스트도 넣어두자. 아, 지금 집이니까 이정도만 생각해두고 나머지는 회사가서 생각해야지. 좀 쉬자.

이렇게 오늘 하루도 다 가는구나 'ㅅ'

짤방



크리에이티브 커먼즈 라이센스
Creative Commons License
2008/08/31 12:21 2008/08/31 12:21
Tag

http://zeru.kr/blog/trackback/452

  1. 2008/09/02 07:34 [Edit/Del] [Reply]
    도대체 무슨 우주의 언어를 말하고 있는건지 헐 ㅋㅋ

댓글을 남겨주세요

Name *

Password *

Link (Your Homepage or Blog)

Comment

Secret