위와 같은 에러가 발생했다. 

netstat -an | find "1099"

cmd에서 위와 같은 명령어로 1099 포트를 사용 중인 application을 찾아봐도 아무런 결과도 나오지 않았다.

-> 현재 1099 포트를 사용하는 application 없음.

-> 할당된 1099 포트에서 제거하고 다시 할당할 수 없음. (애초에 할당된 것이 아니기 때문)

 


해결방법

netsh interface ipv4 show excludedportrange protocol=tcp

해당 명령어를 수행하여, 예약된 포트를 확인할 수 있다. 

 

해당 문제는 1099 포트가 "reserved" 되어 있다는 것이었다.

포트가 예약된 경우에서는 해당 포트를 사용하지 못한다. 

1099 포트가 1024~1123에 해당하기 때문에, 할당하지 못하는 것이다.

 

이와 같은 경우에서는,

netsh int ipv4 set dynamicport tcp start=49152 num=16383

명령어를 통하여 포트의 예약을 취소할 수 있다. 

참고로 해당 명령어는 관리자 권한에서 실행되어야 한다. 

 

이후 pc 재부팅을 하면, 포트 예약이 취소된 것을 확인할 수 있고 

1099 포트를 할당받아 tomcat 서버 구동에 성공할 수 있다. 

 

성공!

 

 

 

참고한 블로그

https://cloudscape.kr/blog/2021/01/address-localhost1099-is-already-in-use/

 

Address localhost:1099 is already in use – Cloudscape's Blog – Wer rastet, der rostet.

IntelliJ에서 Tomcat Server를 구동하면 계속 ‘Address localhost:1099 is already in use’라는 메시지를 보여주며 실패했다. netstat -aon | find "1099" 또는 lsof -i:1099 등으로 확인해도 해당 포트를 사용하는 application

cloudscape.kr

 


안녕하세요! 오랜만에 글을 쓰네요... 

 

이번 포스팅은 미리 Android studio가 깔려있다는 가정 하에 시작합니다.

제 버전은 Android Studio Arctic Fox | 2020.3.1 Patch 3 입니다.

 


1. 프로젝트 생성

 

새로운 프로젝트를 생성해줍니다. 프로젝트 템플릿에는 여러 가지가 있는데요, 이 Activity 중 필요한 Activity를 고르면 됩니다.

 

여기서, Activity란

사용자와 상호 작용하는 가장 기본적인 요소로서, 어플리케이션에서 사용자에게 보여지는 화면을 의미합니다.

 

저는 현재 Hello World!만 출력하는 애플리케이션을 만들 것이기 때문에,  Empty Activity를 사용했습니다.

Empty Activity란, 심플 텍스트 컨텐츠가 있는 단일 레이아웃 파일과, 빈 Activity를 생성하는 템플릿입니다. 

또한 생성 시에 위에서 언급한 심플 텍스트에 Hello World!가 이미 들어있어서 사실 템플릿만 만들면 됩니다ㅎㅎ... 

 

Name: 애플리케이션의 이름

Package name: 앱의 고유 ID처럼 사용되는, 패키지 이름 (고유 ID처럼 사용되기 때문에 막 설정 x)

Minimum SDK: 애플리케이션이 지원하는 가장 낮은 레벨의 SDK(개발 도구) 

 

Minimum SDK 설정이 중요한데, 너무 낮아도 지원 안 하는 서비스가 있을 수 있고 너무 높으면 지원할 수 있는 기기가 적어서 잘 설정해야 한다고 합니다. 저는 일단 사진에서와 같은 SDK로 설정했습니다. 

 

SDK는 다 아시겠지만 개발 도구 모음으로, 저게 있어야 개발이 됩니다. 저도 자세히 찾아본 적은 없는데.. 라이브러리도 있고 디버거도 있고 여러 파일들이 있는 걸로 압니다. 

 

2. Virtual Device 생성

 

상단 Tools-AVD Manager

AVD Manager로 가상 에뮬레이터를 생성할 수 있습니다.

하단의 create Virtual Device를 누르면 Virtual Device Configuration 창이 뜹니다. 

여기서 원하는 기기를 선택하면 됩니다.

저는 Nexus 5X를 선택했습니다.

 

가상 장치를 생성하는 화면에서 여러 프리셋 중 하나를 골라야 합니다.

안드로이드 가상 장치를 사용하기 위해서는 이러한 이미지들이 필요하기 때문에 각자 따로 다운을 받아줘야 합니다. 

저는 Nougat 버전, Android 7.1.1을 다운로드 받았습니다.

 

이후 화면 설정이나... 그런 것들은 기본 설정으로 해줬습니다. 

대신 Startup orientation은 portrait로 설정해줬습니다.

=> 시작 시, 화면이 정방향으로 보이도록 

 

 

3. 기타 문제들

이후 빌드를 했을 때,

성공적으로 실행이 안됐습니다 ㅠㅠ

build fail의 이유를 보면 license for package android sdk build-tools 30.0.2 not accepted라고 되어있습니다.

sdk 다운 받을 때 뭐가 안 받아졌던 것 같습니다.

빠르게 받아주도록 하겠습니다.

File-settings

 

지금은 제가 다 받아놨는데 원래 Licensing Library, google Play services 등이 받아져있지 않아서

체크하고 다 받아줬습니다. 

 

이후 run 했을 때,

성공적으로 실행되는 것을 볼 수 있습니다. 화면을 켰는데 바로 앱부터 나오는 이유는, 이유가 있습니다.

밑에서 구조 설명 시에 설명하겠습니다. 

 


4. 프로젝트의 구조 

 

기본적으로 프로젝트를 생성하면 manifests, java, res 파일이 존재하게 됩니다. 

 

java 파일에서는 아까 설정한 패키지가 세 개나 있습니다. 이는 java언어로 작성은 하지만, 안드로이드가 JVM에서 돌아가는 것이 아니기 때문에 java에 환경 이외에도 안드로이드 영역에서 돌아가는지 확인하기 위한, test 부분이 존재하는 것입니다. 

 

<Main Activity>

여기서  MainActivity 클래스를 정의합니다. 이는 AppCompatActivity를 상속한다고 하는데,

몰라도 될 것 같고요 (아직까지는...) 이 코드는 프로젝트를 생성하면 자동적으로 만들어지는 코드입니다.

여기서 알아두어야 할 것은 setContectview(R.layout.activity_main); 입니다. 

 

activity_main.xml 파일에서 UI를 담당하는 레이아웃을 관리하기 때문입니다. 

activity_main 파일은 res(resources)에 있습니다. 

layout은 code, design, split 과 같이 여러 방법으로 작성할 수 있습니다.

 

위에서 Hello World! 를 설정하지 않아도 기본적으로 나온다고 했는데,

activity_main.xml 파일에 기본적으로 정의되어 있기 때문입니다.

 

res 구조를 이해하기 위해서는 layout, mipmap, values 를 알아야 합니다. 

layout: 위의 activity_main.xml과 같이 화면 UI 담당하는 레이아웃 리소스

mipmap: 아이콘과 같은 이미지

values: 문자열, 정수, 컬러와 같은 값을 포함하는 xml 파일 

 

일단 layout, mipmap, values 모두 프로젝트 진행 시에 필요한 리소스라는 것만 알면 될 것 같습니다.

 

strings.xml 파일을 보면,

app_name을 정의해주고 있습니다. 저는 Hello Android로 정의했습니다.

그래서 위에 에뮬레이터에서 앱 이름이 Hello Android로 출력되었던 것입니다. 

이와 같이 저는, 파라미터를 정의하는 파일처럼 받아들였습니다. 

(아닐 수도 있음...)

 


5. Manifest 파일

 

저는 지금 Activity가 두개라서 조금 심란해 보일 수도 있는데,

<activity></activity> 사이에 android:name =".MainActivity" 인 부분만 보면,

<intent-filter>형식이 있습니다.

 

제가 위에서, 휴대폰을 켜자마자 기본 바탕화면이 보이지 않고 앱이 실행되었다고 했는데, 이 부분 때문입니다. 

1. <action android:name="android.intent.action.MAIN" />

2. <category android:name="android.intent.category.LAUNCHER" />

 

.MainActivity가 1. 시작점이 될 수 있고 2. 런처에 표시될 수 있음 을 나타냅니다. 

(런처란, 설치된 어플리케이션 목록) 

 

그래서 실행 시에, 해당 Activity가 바로 실행된 것입니다. 

 

여기서 시작점이란? 

c, c++, java에서는 모두 main 메소드에서 시작을 합니다.

이들은 모두 main 메소드가 시작점으로 설정된 것입니다.

하지만 안드로이드에서는 main과 같이 고정된 시작점이 없습니다.

시작점을 주입해줘야 한다는 것입니다. 

 

 

시작점 대신 사용할 수 있는 4가지 컴포넌트 
Activity
Service
BroadCast Receiver
content Provider

 

 

4가지 컴포넌트로 진입이 가능합니다.

해당 진입점을 manifest 파일에 적어둡니다. 

 

이외에도, 많은 정보를 가져야 합니다.

앱에서 사용되는 컴포넌트, 권한, 패키지 이름 등등이 선언되어 있어야 합니다. 

현재 프로젝트에서는 Activity 컴포넌트만 사용되었기 때문에 매니페스트 파일에 Activity만 정의되어 있습니다.

 

 

 

https://programmers.co.kr/learn/courses/30/lessons/12951

 

코딩테스트 연습 - JadenCase 문자열 만들기

JadenCase란 모든 단어의 첫 문자가 대문자이고, 그 외의 알파벳은 소문자인 문자열입니다. 문자열 s가 주어졌을 때, s를 JadenCase로 바꾼 문자열을 리턴하는 함수, solution을 완성해주세요. 제한 조건

programmers.co.kr

 

안녕하세요! 오늘은 JadenCase 문자열 만들기 문제를 다뤄보겠습니다.

저는 두 개의 정답이 나왔는데요.

1. 간결하지만 join함수를 사용하는 알고리즘

2. 1보단 덜 간결하지만 join함수를 사용하지 않아, 보다 직관적인 코드

 

제 개인적인 생각으로는 2번이 좋은 코드라고 생각하는데 다들 짧은 코드를 칭찬하시더라구요!

무슨 코드가 더 좋은 코드인지는 더 알아가야 할 것 같습니다. 

 

 


1. 문제 설명

위의 링크에 접속하시면 문제가 나옵니다.

제가 중요하게 생각했던 부분은

1. 첫 글자만 대문자이고(숫자나 문자일 경우에는 그대로)

2. 나머지 글자는 모두 소문자이다(숫자, 문자는 위와 같습니다.)

3. 공백 값도 고려해야 한다. 

입니다!

 

제일 어려웠던 부분은 3. 공백 값도 고려한다는 부분인데요, 

만약 "   banana" 가 input으로 들어왔다면, "  Banana" 가 출력되어야 합니다.

공백을 버리면 안되고, 공백은 문자로 취급하지 않습니다. 

 


2. split(), join(), upper(), lower() 함수와 코드 설명 

2-1. split() 함수 

#앞으로 설명을 위해 문자열을 str, 리스트를 lis라고 칭하겠습니다!

 

str.split(' ') 

= 문자열 str을 ' '(공백)으로 구분하여, 리스트를 반환하겠다. 라는 뜻입니다. 

str="a b c" 라면, str.split(' ')=["a", "b", "c"] 가 됩니다. 

 

str.split() 

이러한 형태의 함수 또한

str="a b c"라면, str.split()=["a", "b", "c"]가 됩니다.

 

하지만 둘의 차이점은 str.split(' ') 은 확실히 공백이 구분자인 것입니다.

 

만약 str="vvBanana" (여기서 v는 공백입니다. 스페이스요) 라면

 

str.split(' ')=["", "","banana"] 로 구분될 수 있습니다.

앞의 공백 또한 구분자로 여겨 ""v"" (빈 문자열-v-빈문자열) 의 형태로 인식합니다. 

vvbanana는 "" v "" v banana -> ["", "", banana] 의 형태가 됩니다. 

 

반면에,

str.split()=["banana"]의 형태가 됩니다. 

2-2 join() 함수

join() 함수는 split()과 반대로, 리스트를 문자열로 바꿔주는 함수입니다. 

input: 리스트 output: 문자열

 

기본적인 형태는

"구분자".join(lis) 

로, lis(리스트)에 있는 값들 사이사이에 구분자를 넣은 문자열을 반환하여줍니다.

 

lis=['a', 'b', 'c']

" ".join(lis) 는 "a b c" 입니다. 

 

2-3 upper() 함수

upper() 함수는 문자열을 모두 대믄자로 변환해주는 함수입니다. 

str.upper() 

구조로 사용하면됩니다. 

2-4 lower() 함수

lower() 함수는 문자열을 모두 소문자로 변환해주는 함수입니다. 

str.lower() 

구조로 사용하면 됩니다. 

 

저는 총 코드를 두 개 제출했습니다.

 

1번)

def solution(s):
    words=s.split(' ') #공백을 기준으로 분할 (빈 문자열이 포함 됨)

    answer=[w[0].upper()+w[1:].lower()+' ' if w!='' else ' ' for w in words]

    return ''.join(answer)[:-1] #문자열로 반환하기 위함

여기서 

answer=[w[0].upper()+w[1:].lower()+' ' if w!='' else ' ' for w in words] 

의 구조를 설명해보겠습니다. 

반환형이 리스트이기 때문에 리스트 안에 for과 if문을 넣었습니다. 

 

공백을 기준으로 분할된 문자열의 리스트를 기준으로 for문 반복합니다. 

각각 리스트의 요소인 w가 빈 문자열이 아니면 -> 공백이 아닌 것(문자열임)

해당 문자열의 첫번째 단어만 대문자로 바꾼 후, 

슬라이싱 기법을 사용하여 w[1:], 즉 해당 문자열의 첫 번째 단어 이후부터 마지막 단어까지 소문자로 바꿔줍니다. 

(여기서 문자열 사이에는 원래 공백이 있으므로 공백을 포함합니다. ) 

 

만약 w가 빈 문자열 이라면, 공백도 당연히 포함되어야 하기 때문에 공백을 넣어줍니다. 

 

한 문장에 리스트, if-else, for문을 다 넣기 위한 형태는 위와 같이 됩니다. 

 

 

2번)

def solution(s):
    answer = ''
    words=s.split(' ')
    for i in words:
        if i=='':
            answer+=' '
        else:
            answer+=i[0].upper()+i[1:].lower()+' '

    return answer[:-1]

 

사실 전 직관적인 것이 좋아서 이 코드가 더 좋다고 생각합니다. 

2번 같은 경우에는 answer을 빈 문자열로 설정하여, for문을 통해 answer에 문자들을 점점 더해줍니다.

for문의 내용은 위와 같습니다. (리스트의 경우를 문자열로 바꿨다고 생각하면 됩니다.) 

 

 


사실 python을 공부한 적이 없어서 문법 하나하나 찾아보는 게 시간이 많이 걸리는 것 같습니다. 

근데 언어는 자꾸 까먹으니깐... c++ c java 다 전생같네요.

 

+ Recent posts