어릴적, 초등학생 시절 부모님께서 크리스마스 선물로 사주신 파랜드택틱스 시리즈

나이가 들어도 몇번이고 완결을 봤었는데

파랜드 택틱스 1~3편과 다르게 파랜드택틱스4는 온갖 팅김과 버그로 제대로 클리어 해본적이 없었다

 

몇 가지 패치가 나왔다곤 하지만 그럼에도 팅기는 문제는 여전했고

게임 특성상 저장이 가능한 장소가 한정적이다 보니 레벨노가다 혹은 세이브포인트가 나올때까지 이동하다가 팅기면 의욕이 팍 꺾이곤했었다

 

많은 고민 끝에 exe파일을 뜯어 내 입맛대로 고쳐보기로 결정

여러가지 목적과 목표가 있었고, 성공했고, 완결을 볼수있었다!!

 

너무 많은 패치를 해서 모든게 기억나진않지만

1. F5 버튼을 통한 언제 어디서든 세이브 기능 (세이브 포인트 없이 언제든지 자유 세이브)

2. 경험치 배율 조정 (빠른 스토리 밀기 위해 노가다 구간 스킵)

3. 백지도 100% 패치 (맵 마다 백지도 사용시 100%)

4. 능력치 에디터

5. 아이템 에디터

6. 팅김 방지 패치 (완벽하게 잡을순 없었지만 완결을 볼때까지 10회 미만으로 팅김)

 


 

우선 회고에 앞서 환경을 제공해준 두기님께 무한한 감사를 드립니다.

 

이번에 진행한 패치중 가장 인상깊었던 부분은 원작의 제한된 세이브 포인트 구조를 우회하지 않고 파랜드택틱스4의 세이브/로드 구조와 FOS 저장 구조를 역분석하여 특정 핫키를 통해 원작 슬롯 UI 호출 및 로드 시 원작이 하드코딩한 복귀 지점을 제거하여 세이브 파일에 기록된 실제 맵 좌표 방향으로 복원되도록 수정한 것이다.

 

다행히 두기님의 배포본을 찾을수 있었고, 해당 파일을 분석해본 결과 두기 배포본은 도스박스 SVN위에서 윈도우95를 부팅한뒤 FAT16 디스크 이미지 (image.img)를 마운트하여 FT4.EXE를 실행하는 구조였다.

덕분에 런처나 도스박스 자체를 교체하기보다 image.img 내부 FT4.EXE 패치하는 방법을 채택했다.

 

처음 시도는 자유 세이브 로드와 팅김 방지 패치였다.

팅기는 구간을 잡아내려해도 많은 이벤트와 오류가 엉켜있어 전부 잡을수가 없어 최소한의 패치만 진행하려는 계획이었기 때문에

팅겨도 문제가 없도록 (전투 후 언제든 세이브하면 되니) 세이브/로드 구간과 팅기는 구간을 먼저 분석해 보았다.

 

초기 분석 결과 DirectDraw 자체보다 파일 I/O, 이벤트 스크립트 VM, 리소스 로더, UI 인덱스 검증이 더 위험해 보였다.

특히 이벤트 스크립트 로더의 CreateFileA 실패 판정은 코드 수준에서 명백한 결함이 보였다.

 

1.1 CreateFileA 실패값 판정 오류

이벤트 .SRC 파일을 열지 못해도 실패를 성공으로 오인할 수 있었고, 이후 ReadFile 및 이벤트 실행이 계속되며 잘못된 버퍼상태를 사용할수도 있어보여 실패값 판정, ReadFile 성공 여부와 실제 읽은 길이, 파일 크기 일치 여부를 함께 검사하도록 수정했다.

원본 개념 코드:
HANDLE h = CreateFileA(...);

if (h == 0) { //잘못된 검사
	return 0;
}

Windows 의 실제 실패값 :
I NVALID_HANDLE_VALUE == (HANDLE) -1 == 0xFFFFFFFF

 

1.2 안정화 수정 범위

- 이벤트 해더 0x408 bytes의 정확한 읽기 검증 및 선언 크기/실제 파일 크기 검증

- 이벤트 본문 ReadFile 실패 시 메모리 해제 포인터 초기화 후 안전한 실패 반환

- 이벤트 로더 반환값을 무시하던 상위 호출부 수정

- 이벤트 block index 0..255 범위와 script code pointer NULL 방어

- 리소스 로더의 CreateFileA / GlobalAlloc / ReadFile 실패 처리 추가

- 2x2 선택 UI에서 마우스 hit ID 가 정상 범위를 벗어날 때 무시하도록 3개 루틴 보강

- 원본 .text의 미사용 raw 영역에 444bytes의 안전검사 코드 주입, 실행파일 크기는 유지

 

1.3 FOS 세이브 포맷 역분석

강제세이브를 구현하기 위해 처음부터 세이브 포맷을 새로 만드는 대신 원작의 저장 UI와 저장 함수를 재사용

여기서 약간의 문제가 발생했는데, UI구현과 저장기능을 완료했지만 어째서인지 로드만 하면 다른 위치혹은 맵 바깥에서 로드되는 문제가 발생하였다.

원인은 생각보다 간단했는데도 불구하고 원인을 찾아내는데 상당한 시간이 걸렸음

7~8번 패치를 진행하며 발견한것은 슬롯 명칭과 로드 경로는 정상이지만 실제 로드 위치는 내가 저장한 위치가 아닌 각 맵 인덱스의 '여관', '호텔', '세이브포인트' 로 강제된것을 발견

이 패턴이 'Save Point = Resume Point' 구조를 강하게 시사했고, 실제 디스어셈블 결과 하드코딩된 복귀 좌표를 발견했다.

 

1.4 원작 로더의 하드코딩된 복귀 시점

context = 1 로드 경로를 추적한 결과, 서로 다른 세곳의 디스패치 코드가 동일한 하드코딩을 수행하고 있었다.

즉 세이브 파일에 실제 X/Y가 들어있어도 최종 맵 초기화 단계에서 이를 덮어쓰고 있었음

 

원작의 context == 1 로드 로직

if(saved_map == 75){
	SetMapSpaws(
    	map = 75,
        x = 0x590, // 1424
        y = 0x450, // 1104
        z = 0,
        dir = 1
    );
}
else{
	SetMapSpaws(
    	map = 8,
        x = 0x2F0, // 752
        y = 0x270, // 624
        z = 0,
        dir = 1
    );
}

 

이 한 덩어리의 로직이 모든 현상을 설명했다. map 75에서는 항상 여관의 같은 위치로 돌아가고, 그 외 context =1 저장은 map 8의 지정 좌표로 강제 되었음.

그래서 저장 기능은 FOS에서 복원한 live party 구조체를 이용하여 context = 1 하드코딩 분기 세곳을 공통 helper로 보내고, helper가 저장된 map ID와 리더 X/Y/Z 방향을 SetMapSpawn()에 그대로 전달한다.

 

call 0x5D36E0
call 0x63A00D ; saved map ID

push [0x1ADDC90]; direction
push [0x1ADDC8c]; Z
push [0x1ADDC88]; Y
push [0x1ADDC84]; X
push eax ; map ID

call 0x5D3580 ; SetMapSpawn(map, x, y, z, dir)
add esp, 0x14
ret

 

1.5 최종 사용 방식

- F5 버튼 핫 키 등록

- F5 버튼을 통해 원작 SAVE 슬롯 UI 호출

- 슬롯 선택

- SAVE

- LOAD 시 맵 별 고정 좌표가 아닌 저장된 saved map + lader X/Y/Z 실제 위치를 spawn 위치로 전달

 

1.6 결과

 

세이브 포인트가 없는 위치에서 강제 세이브 기능 완료~!

 

2.1 패처 (백지도 및 경험치 배율, 에디터 등)

 

위와 같은 형태로 만들었으며 스토리를 빠르게 밀기위해 호다닥 제작

중요한건 팅김 방지 패치와 강제 세이브 기능이므로 위 기능 제작 과정은 생략합니다

귀찮음 이슈

 

3.1 아무튼 결론

사심을 채우기 위한 프로젝트 였는데 생각보다 재미있게 작업한것 같다.

파랜드 택틱스4의 FOS는 최소한 핵심 상태를 평문 구조체에 가까운 형태로 저장하고 있고, 위치 좌표도 세이브파일에 존재해서 가능한 작업이었음. 지정된 장소에서만 저장 제약은 UI 제한만이 아니라 로더 설계와 연결 되어있는 부분이 재미있었다.

강제 세이브 기능만 추가해야지 헤헤 라는 내 얕은 생각을 박살낸 로더 설계...하... 이것땜 삽질한거 생각하면 증말...

아무튼 로드 마지막 단계의 spawn 결정을 함께 수정하여 해결할 수 있어서 다행이다.

7~8번의 패치를 진행하면서 실패한 경험들이 context, state machine, 파티 snapshot, 하드코딩 spawn의 역할을 구분하는데 핵심적인 데이터가 되었음

게임을 재구현한다거나 FOS 포맷을 새로 작성하지 않고 원작 UI/직렬화/맵 초기화 함수를 재사용하여 비교적 작은 바이너리 패치로 기능 확장 및 수정에 성공할 수 있어서 재미있는 경험이었다.

 

 

아주 재미있었다!!헤헤헿

드디어 완결봤다 ㅠㅠ

728x90

독학으로 React를 공부하는 만큼 깨지고 부숴져가며 공부 기록을 남길 예정이다.

개발 환경은 Window와 macOS를 두개 다 사용할 예정

그럼 두개재

 


1. 개발 환경

os terminal ide
window powerShell vs code
macOS terminal vs code

 

2. 설치 해야 할 것

  1. node js : javascript Runtime 용
  2. npm(node pakage manager) : React를 개발할 때 사용할 Pakage들을 당겨오기 위하여
  3. vs code : 이미 사용중이지만 설치 안되신 분들을 위하여 링크 남겨둠

NodeJS 설치

  • 설치 링크 : https://nodejs.org/en
  • 위 링크에서 Node.js를 다운받아 설치 후 확인
  • 확인 방법 : powershell 혹은 terminal에서 ‘node —version’ 입력
$ node --version // 입력시
v18.15.0 // 현재 설치된 node 버전 출력

// Node.js를 설치하면 npm도 같이 설치 되기 때문에 확인 필요

$ npm --version // 입력시
9.5.0 // 현재 설치된 npm 버전 출력

 

VS Code 설치


이렇게만 해도 React를 공부할 준비는 끝이 난다.

참 쉽죠? 다음강부터 열심히 공부해 보자

 

728x90

몸풀기로 쉬운 코테 몇개 풀다가 생각지도 않은곳에서 시간을 너무 끌어버렸다.

바로 분수의 덧셈.

일단 정답은 맞췄지만 정답 도출까지 시간이 너무 오래걸렸기에 복습차 기록을 남긴다.

 


문제 설명

첫 번째 분수의 분자와 분모를 뜻하는 numer1, denom1, 두 번째 분수의 분자와 분모를 뜻하는 numer2, denom2가 매개변수로 주어집니다. 두 분수를 더한 값을 기약 분수로 나타냈을 때 분자와 분모를 순서대로 담은 배열을 return 하도록 solution 함수를 완성해보세요.

제한사항과 입출력 예

입출력 예 #1

- 1/2 + 3/4 = 5/4 입니다. 따라서 [5,4]를 return 합니다.

입출력 예 #2

- 9/2 + 1/3 = 29/6 입니다. 따라서 [29,6]을 return 합니다.

 


using System;

public class Solution {
    public int[] solution(int numer1, int denom1, int numer2, int denom2) {
        int[] answer = new int[2];
        
        var top = numer1 * denom2 + numer2 * denom1;
        var bottom = denom1 * denom2;
        var max = 0;
        for(int i = 1; i <= top; i++)
        {
        	// 분모 그리고 분자를 i로 나누어 0이 될때가 최대공약수이다.
            if(top % i == 0 && bottom % i == 0)
            {
                max = i;
            }
        }
        answer[0] = top / max;
        answer[1] = bottom /max;
       
        return answer;
    }
}

1보다 큰 최대 공약수가 없을땐 max에 1이 들어간다.

즉 분모와 분자가 기존 그대로 삽입됨.

 

더 나은 방법이나 질문은 댓글 달아주세용 :)

728x90

3년전 Java를 처음 배우며 Spring도 함께 교육은 받았었는데,

안타깝게도 코로나가 터지며 갑자기 비대면 수업으로 전환되고

제대로 진도를 빼지 못한채 학원을 수료했었다.

 

개발 1년차 취업한 회사에서 C#으로 전향하고 응용프로그램만 만지다,

가끔 Web이 필요할땐 Asp.net으로 개발을 해왔는데

최근 Spring과 React에 관심이 생겨 이렇게 곻부 기록을 남겨본다.

깨부 시작전 현 상황 체크를 해보자면 이렇다.

 

 현재 은다민의 상황
 - 지금까지 대부분의 개발은 C#으로 함 (응용프로그램 / Web)
 - Spring 거의 기억 안남
 - React 아예 모름
 - 기본적인 html / css / js 사용 가능


1. 개발 환경 선택

1. os : Window 10 , Mac OS Monterey (M1)
2. ide : IntelliJ (spring) , vscode (react)
3. database : MySQL
4. api : Swagger

 

  • os는 window와 mac을 둘 다 사용하는지라 언제 어디서든 개발할 수 있도록 선택
  • 사실 ide에서 고민을 많이했다. IntelliJ에서 React를 지원해주기 때문에 사실 한곳에서 모두 개발할 수 있지만,
    이 경우 Spring Boot와 React 애플리케이션을 각각 실행해야 하기 때문에 개발 환경 설정이 복잡해진다는 단점과
    Front-End의 관점에서 개발을 해보고 싶기 때문에 (추후 협업을 위한 경험) 굳이 개발 환경을 나누어 주었다.
  • 아직 대량의 데이터 처리를 동시에 할 프로젝트를 생성할것이 아니라서 MongoDB와 MySQL중 MySQL 선택
  • Swagger와 PostMan중 어떤것을 사용해도 상관없지만, ASP 개발을 할때 사용했던 익숙한 Swaager를 선택

2. 개발 환경 통합

나는 Spring과 React 애플리케이션을 각각 개발하기 때문에 이 둘을 연동하는 통합 작업이 필요하다.

React에서 Rest API를 호출하여 Spring Boot에서 구현한 API를 통해 데이터를 주고 받을수 있도록 작업하려고 한다.

WebSocket을 활용하여 서버와 통신하는 방법도 있지만, 이는 양방향 실시간 통신을 지원하는 프로토콜

즉, 채팅이나 게임같이 연결을 유지하며 실시간으로 데이터를 주고 받는 방식이기 때문에

프로젝트 방향과 맞지 않을거라고 판단하여 API 호출 방식을 선택하였다.

 

REST API 방식 : HTTP 프로토콜 기반으로 클라이언트 - 서버 모델을 따르는 웹 서비스 아키텍쳐.
클라이언트와 서버 간에 비동기적 데이터 통신이 가능. HTTP Method (GET, POST, PUT, DELETE)를 사용하여
데이터를 조작가능. 간단하고 직관적이며 다양한 클라이언트와 서버에서 사용 가능.
단순한 데이터 전송이나 CRUD 작업을 수행하기 위해 선택하였음

WebSocket 방식 : 양방향 실시간 통신을 지원하는 프로토콜.
클라이언트와 서버가 한 번 연결하면 연결을 유지하며 실시간 데이터 통신이 가능.
채팅,게임,주식 시세 같은 어플리케이션을 만들때 사용.
이처럼 실시간으로 데이터를 주고받거나 푸시 알림등의 기능이 필요할때 사용하면 좋다.

 

다음편에는 개발 환경 셋팅을 해보자

728x90

 

오늘은 데이터 타입에 대하여 알아보자.

데이터 타입(Data Type)이란 무엇일까?

 

데이터 타입 (Data Type)

데이터 타입은 쉽게 생각하면 너무 쉬운 명칭이다.

말 그대로 데이터의 타입. 즉 값의 형태를 의미한다.

 

이렇게 말해서는 잘 이해가 안갈수 있기 때문에 예시를 먼저 보여주겠다

 

'A' -> 우리는 이것을 '문자' 라고 표현한다
"ABCDEF" -> 우리는 이것을 '문자열' 이라고 표현한다
9 -> 우리는 이것을 정수 라고 표현한다
3.14 -> 우리는 이것을 소수 라고 표현한다

이렇게 어떠한 값의 형태를 우리는 Data Type이라고 부른다.

 

그렇다면 그냥 문자면 문자, 숫자면 숫자로 사용하면 되는걸 왜 이 사단을 부리는걸까?

 

데이터 타입을 깊게 파면 한도 끝도 없으니 간단하게 설명해보자

숫자 10과 문자열 "10"은 다르다. 누가봐도 둘다 10이지만

숫자 10은 프로그램 안에서 덧셈, 곱셈등 연산이 가능하다.

그렇다면 문자열 "10"은 어떨까?

이것은 숫자가 아닌 "10" 이라는 문자를 표현한 것이기 때문에 연산이 안된다.

 

Swift는 다른 언어에 비해 타입에 대해 엄격한 편이다.

꼭 타입을 열심히 공부해서 에러가 나지 않는 코드를 짜보자

 


데이터 타입의 종류

  • Bool (Boolean의 약자)
  • 참과 거짓을 표현
var trueType : Bool = true // true 값을 가진 Bool Type
var falseType : Bool = false // false 값을 가진 Bool Type

 

  • Int (Integer의 약자)
  • 64bit
  • 정수를 표현
var someInt : Int = 100 // 100의 값을 가진 Int Type 양의 정수
var someInt2 : Int = -999 // -999의 값을 가진 Int Type 음의 정수
// 3.14 처럼 소수는 사용 x

 

  • UInt (UnSigned Integer의 약자)
  • 부호가 없는 정수 (양의 정수만 표현)
var someUInt : UInt = 100 // 100의 값을 가진 UInt Type의 양의 정수
// -100 처럼 음수는 사용 x

 

  • Float
  • 32bit
  • 부동 소수
var someFloat : Float = 3.14
var someFloat2 : Float = 3 // 소수는 정수에 포함되어있기 때문에 사용 가능

 

  • Double
  • 64bit
  • 부동 소수
var someDouble : Double = 3.14
var someDouble : Double = 3 // 정수라도 가능
//하지만 Double = Float은 안된다.

 

  • Character
  • UNICODE를 표현한 '문자'
var someCharacter : Character = "A"
var someCharacter2 : Character = "가"
var someCharacter3 : Character = "1"
// "하하하" -> 한 문자가 아니기 때문에 안됨

 

  • String
  • 문자가 이어진 "문자열"
var someString : String = "가" // 문자열은 문자를 포함하고 있기 때문에 가능
var someString2 : String = "하하하"
var someString3 : String = "웃으면 복이와요."

print(someString2 + someString3) // 문자열을 연산으로 합칠수 있다
// 하하하 웃으면 복이와요.

// String = Character 는 안됨

 

이 Decimal이라던가 여러가지 타입이 존재하나 가장 많이 사용하는 타입 4가지

Bool / String / Int / Double

이 4가지라도 확실히 기억하고 가는것이 좋다.

 

굳이 지금 억지로 외우지 않아도

변수나 상수를 선언할때 꼭 사용하게 되므로

자연스럽게 익혀나가는것이 좋을것 같다.

728x90

'개발 > Swift 문법' 카테고리의 다른 글

[Swift문법]01. Swift 시작하기 / 상수와 변수  (0) 2022.07.06

 

Swift 공부를 시작하며

29살이라는 늦은 나이에 Java 웹개발로 개발을 시작하여

현재는 C#기반 응용프로그램 및 ASP 웹개발자가 되었다.

평소에 관심을 가지지 못했던 App에 도전하며 매일 공부하는 것을 기록해 나가려 한다.

혹여나 이 글을 보는 사람들에게 도움이 되길 바라며 :)

 


Swift를 공부하기 위해서 M1 Pro를 구매하였다.

아무래도 IOS는 Window에서는 개발하기 제한이 많다보니 (Flutter등 다른 방안은 있다)

IOS Native App에 관심도 생긴김에 큰마음 먹고 구매 하였다.

 

우선 Xcode를 설치해보자.

 

Xcode 설치하기

https://apps.apple.com/kr/app/xcode/id497799835?mt=12 

다음 링크에서 Xcode를 설치할 수 있다.

AppStore에서도 Xcode를 검색하면 쉽게 찾을수 있으니 다운로드 받아 설치하자

 

 

PlayGround 실행하기

현재는 문법 공부를 위해 UIkit이나 SwiftUI에 손을 대지않으려 하기 때문에

대부분의 문법 공부는 PlayGround를 활용할 것이다.

PlayGround는 말그대로 간단한 코드를 작성 및 실행해 볼 수 있는 환경을 말한다.

우선 Xcode를 실행해보자

Xcode 최초 실행 화면

해당 화면이 잘 나타났다면 다음 순서를 따라가보자

아무것도 건들지 않은 상태에서 상단 메뉴중

File -> New -> Playground 클릭

Blank 선택 후 Next 버튼 클릭

 

저장할 파일명과 경로 설정후 Create 버튼 클릭

Tag는 굳이 적어주지 않아도 괜찮다.

 

Playgorund 초기 생성 화면

이렇게 Playground 환경을 만들어 보았다.

이제부터는 캡처 화면이 아닌 코드를 통해서 기록해 나갈 예정이다.

 


변수와 상수

3년전 프로그래밍을 시작할때 내가 무서워 했던 단어이며,

이미 다른 프로그래밍 언어를 경험해본 개발자들이라면 익숙한 단어이다.

변수(Variable)란 값이 변할수 있는 메모리 공간이다
상수(Constant)란 값이 변할수 없는 메모리 공간이다

이렇게만 보면 감이 잘 오지 않을수도 있다.

다음의 코드를 보자.

var myAge : Int = 31
let myName : String = "은다민"

어려워 할 필요 없다.

하나하나 살펴보자

var myAge : Int = 31

// var -> 변수임을 선언
// myAge -> 변수의 이름
// Int -> 변수의 타입
// 31 -> 변수의 값

let myName : String = "은다민"

// let -> 상수임을 선언
// myName -> 상수의 이름
// String -> 상수의 타입
// "은다민" -> 상수의 값

자신의 나이와 이름을 생각해보자.

내 나이는 매년 한살씩 증가한다. 올해 myAge 안에는 31이 담겨있지만
내년에 myAge는 32가 담겨있어야 한다. myAge의 값은 계속 변하기 때문에 변수인 var를 선언해 주었다.
내 이름은 은다민으로 몇년이 지나던 내 이름은 계속 그대로이다. (개명은 하지않는다는 가정)
myName에는 "은다민"이 담겨져있고, 이는 평생 변하지 않기 때문에 상수인 let을 선언해 주었다.

 

실전 테스트

그럼 변수와 상수에 값이 정말 변하는지, 변하지 않는지 테스트 해보자.

var myAge : Int = 31 //변수 myAge를 생성하고 31의 값을 넣어준다
let myName : String = "은다민" //상수 myName을 생성하고 "은다민"이라는 값을 넣어준다

print("myAge : \(myAge)") //myAge안에 어떤값이 들어있는지 출력해보기
print("myName : \(myName)") //myName안에 어떤값이 들어있는지 출력해보기

myAge = 32 //32라는 값을 myAge에 넣어준다.
myName = "바보" //"바보"라는 값을 myName에 넣어준다. -> 여기서 Error가 날것이다.
// myAge와 myName은 이미 생성된 변수,상수라서 다시 선언해줄 필요없이 변수,상수를 사용할수있다.

print("myAge : \(myAge)")
print("myName : \(myName)")

 

실제 테스트 화면을 참고해보자

실행은 좌측 하단쯤 재생버튼 처럼 생긴 아이콘을 눌러주면 된다.

정말 친절하게도 myName은 let을 선언한 상수라서 값을 변경할수 없다고 Error Message가 나온다.

그럼 변할수 없는 상수 myName = "바보" 만 지워주고 다시 실행을 해보자.

 

 

화면 하단 출력창에 우리가 원하는대로 값이 출력되었다.

이것으로 변수와 상수에 대한 공부를 마친다 :)

728x90

해당 게시글은 개인 라이브러리가 있다는 전제 하에 작성하였습니다.

개인 라이브러리 생성에 대해 궁금하시다면 따로 포스팅 하겠습니다 :)

 

1. 누겟 갤러리 계정 생성

다음 링크에 접속하여 누겟 계정을 생성합니다.

본인이 갖고있는 마소의 계정으로 로그인도 가능합니다.

https://www.nuget.org/

 

NuGet Gallery | Home

The NuGet Gallery is the central package repository for NuGet, the package manager for .NET.

www.nuget.org

 

2. 누겟 패키지 생성 프로그램 다운로드

 

다음 링크에 접속하여 누겟 패키지 생성 프로그램을 설치 합니다.

저는 항상 최신버전으로 사용중입니다 :)

https://www.nuget.org/downloads

 

NuGet Gallery | Downloads

Available NuGet Distribution Versions Visual Studio 2017 NuGet 4.x is included in the Visual Studio 2017 installation. Latest NuGet releases are delivered as part of Visual Studio updates. Available NuGet Distribution Versions

www.nuget.org

 

3. 누겟 패키지 파일 생성

 

배포할 프로그램이 있는 경로에 다운받은 nuget.exe를 이동시킵니다.

.sln 파일이 있는 곳이 아님

cmd를 관리자권한으로 실행 후 해당 경로로 이동하여 다음 명령어를 실행합니다.

성공 메세지가 뜨면 패키지 파일이 생성된것을 확인 할 수 있습니다.

 

생성된 패키지 파일

 

4. 누겟 갤러리에 라이브러리 배포하기

 

패키지 파일 생성까지 완료되셨다면 이제 배포를 할 차례겠네요 !

누겟 갤러리 홈페이지에 접속하여 Upload에 들어가줍니다.

https://www.nuget.org/packages/manage/upload

 

NuGet Gallery | Sign In

Forgot the Microsoft account you used to sign-in?

www.nuget.org

 

패키지 파일을 업로드 시켜주면 검수 과정에 돌입합니다.

 

 

위 사진처럼 Status가 Listed로 변경되면 배포가 완료된것입니다.

Listed로 변경까지는 1분에서 5분정도의 시간이 소요됩니다.

 

이제 배포된 라이브러리(패키지)를 다운받아 제대로 동작하는지 확인하는 과정을 가져볼까요?

 

 

5. 내가 배포한 라이브러리(패키지) 다운로드 및 동작 확인

 

테스트 할 프로젝트를 생성 후 누겟 패키지 관리자에 들어가 본인이 배포한 라이브러리를 검색해 줍니다.

제가 배포했던 DaminLibrary와 Damin.Log가 잘 올라와 있네요.

설치 후 동작 확인도 해봅시다.

 

저는 로그 라이브러리를 테스트 해 보았습니다.

다음 처럼 사용하시면 될 것 같아요 :)

 

 

다행스럽게도 잘 작동하네요 !

 

도움이 되셨으면 좋겠습니다 :)

다음 포스팅에서 또 만나요

감사합니다 !

728x90

'개발 > C#' 카테고리의 다른 글

[C#] 2. 문자 뒤집기 [StringBuilder , SubString] 활용  (0) 2022.03.23
[C#] 1. C#의 시작, Hello World !  (6) 2021.06.25

 

요즘 이직 준비 때문에 코딩 테스트를 보고, 면접 후기를 많이 보고 있습니다.

면접 후기중에 문자열 뒤집기 테스트가 있었다는 글을 보고

신입 개발자분들 중에 문자열에 약하신 분들이 있으실까 강의 남깁니다 :)

 


우선 코드부터 볼까요?

 

string originString = "ABCDE"; // 기준 문자열

int length = originString.Length; // 기준 문자열의 길이

StringBuilder sb = new StringBuilder(); 
//StringBuilder는 String의 재조합보다 참조 메모리를 덜 차지함

for(int i = length-1; i>=0 ; i--) //끝자리부터 도는 이유는 문자열을 역전시키기 위함
{
	sb.Append(originString.Substring(i,1)); 
    //Substring으로 문자열을 한개씩 StringBuilder에 추가해줌
}

string result = sb.Tostring(); //다시 string 타입으로 변환

Console.WriteLine(result);

result의 값은 "EDCBA" 가 됩니다 :)

 

사실 여기서 어려워 할 부분은 Substring() 메서드의 사용이라고 생각해요.

처음 Substring() 메서드를 접했을때 오버로드가 되어있는것을 보았고

startindex와 index를 조합하여 원하는 문자열을 골라 올 수 있는걸 알았고

전 그게 string.Substring(1,3); 일경우 1번째부터 3번째 인덱스의 문자열을 잘라오는줄로만 알고있었죠

자꾸 인덱스 오류가 나고, 쌩뚱맞은 문자열을 리턴 하길래 무슨 문제인가 디버깅 해보았습니다.

 

위의 예제를 활용해서 다시 살펴볼까요?

 


 

string originString = "ABCDE";
string index = originString.Length;

//1. startIndex가 0일경우 
string result = originString.Substring(0); //result == "ABCDE"

//2. startIndex가 1일경우
string result = originString.Substring(1); // result == "BCDE";

//3. startIndex가 0, length 추가했을 경우
string result = originString.Substring(0,length); // result == "ABCDE"; (0부터 5까지 잘라왔기때문)

//4. startIndex가 1, length 추가했을 경우
string result = originString.Substring(1,length); // index오류!!!
//1부터 (B부터) 5번째 길이만큼 자르려면 originString의 length가 6이상이어야 함
//현재 originString의 전체 length는 5이므로 index 오류가 발생

//5. startIndex가 1, length가 1일경우
string result = originString.Substring(1,1); // result == "B";
//1번째 문자열 (B부터) 1번째 길이만큼 자르면 본인을 가져오게됨

//6. startIndex가 1, length가 2일경우
string result = originString.Substring(1,2); // result == "BC";
//1번째 문자열 (B부터) 2번째 길이만큼 자르면 B와 그 다음 문자열인 C를 가져오게됨

 

이해가 쉽게 여러 케이스로 나눠 정리해봤는데 이해가 가시나요?

 

질문이나 조언은 언제든지 댓글로 남겨주시면 감사하겠습니다 :)

728x90

'개발 > C#' 카테고리의 다른 글

[C#] 3. 개인 라이브러리 누겟 패키지 배포하기  (0) 2022.06.20
[C#] 1. C#의 시작, Hello World !  (6) 2021.06.25

+ Recent posts