무조건 goto는 나쁘다?

segfault의 이미지

흔히 프로그래밍 공부하면서 가장 자주 듣는 말중 하나가

"goto문은 절대로 쓰지 마라" 일겁니다.

코드가 혼란스러워진다는게 가장 큰 이유겠죠. (흔히 스파게티 코드라 부르죠)

하지만, 저는 goto문도 적당히 쓰면 효율적이라고 생각합니다.

goto문을 적당히 쓰면 코드가 훨씬 깔끔해지더군요.

(커널 소스 뒤벼봐도 goto문을 심심찮게 찾을 수 있습니다)

오히려 goto문을 억지로 사용하지 않는게 더욱 지저분한 코드를 만들어낼수도 있습니다.

WRITING SOLID CODE에서도 이와 같은 내용을 지적한 걸로 아는데,

여러분의 생각은 어떠신지?

댓글

nanosec의 이미지

다중 루프를 빠저 나가는데는 goto만한게 없다고 생각합니다.

하지만, 엄청난수의 함수와 클래스가 존재한는 큰 프로그래밍 에서는 결코 환영 받지 못하는 존재가 goto라고 생각합니다.

0x2B | ~0x2B
- Hamlet

랜덤여신의 이미지

반복문 여러개를 한번에 빠져나오는 역할로는 괜찮겠지요...
글쎄요... 그 이외의 목적으로는 사용해 본 적이 별로 없어서 잘 모르겠어요... :oops:

jwg286의 이미지

저도 코딩시 goto 를 심심찮게 사용을 하는데요. 주관적인 관점에서 goto 의 사용은 저의 경우, 아래와 같은 경우에 사용합니다.

1. 코딩 생각하기 귀찮을 때. (즉, 직관적으로 goto 를 사용시 충분히 해결할 수 있을 경우.)
2. While 구문 만들기 귀찮을 때.
3. goto 를 제거하기 위해, 함수를 만들기 귀찮을 때.

-_- 즉, 귀찮을 때입니다. 하지만, goto 를 항상 귀찮을 때만 사용하지는 않습니다. 요긴하게 사용될 수도 있지요. 장단점이 항상 있습니다.

다중 루프를 빠져 나올 때, goto 만한게 없다고 하시는 분들도 있으신데, 전적으로 동의합니다. 하지만 goto 를 써야 할 만큼 커다란 다중 루프면 코드를 짤 때, 목적에 대한 접근 방식이 올바른지 한번 생각해 봐야 한다고 생각합니다. 대부분 함수 모듈화를 통해 극복할 수 있으며, 다중 루프에서 빠져나올 때는, 예외 상황 을 많이 염두해 두어야 하지 않을까요. 그만큼 책임감있게 빠져 나와야 할 듯 합니다.

지리즈의 이미지

"goto를 쓰지 말라"라는 말은
goto를 필요한 알고리듬으로 코드를
작성하지 말아라라는 의미로 봅니다.

여기선 goto가 낫다던가,
혹은 goto가 아니면 안돼...
이런 결론이 나오면
알고리듬에 문제가 있다고 판단해야 하지 않는가..
평소에 그렇게 생각하고 있습니다만....

There is no spoon. Neo from the Matrix 1999.

PSG-01의 이미지

간단하게 만들때는 스파게티가 되든 편한거 때문에 Goto를 가끔씩
쓰게 되더군요 :lol:

크게 만들어본적은 없는데 아직 Goto문 쓰면서
큰 불편함은 느껴본적이 없군요 :twisted:

근데 한가지 이상한게 이런 장점이 있는데도 학원 같은데서 보는걸 보면
Goto문을 아예 안가르치더군요 일부러 그런걸까요

-----------------------------------
Playlist :

체스맨의 이미지

goto 문이 반드시 쓰지 말아야 할 것이라면, 아예 그것이 존재하지 않았겠죠.

- 다중 루프 빠져나올 때
- 예외 처리 ( 특히 메모리 할당 중 예외발생시 기존 할당된 메모리 해제 )
- 몇줄의 루틴을 굳이 함수로 빼고 싶지 않을 때
- 등등

에 사용했던 것 같은데요.

goto 레이블을 함수 하나에 2 개 내외로 유지하면, 스파게티처럼 얽히지 않는다고 봅니다. 그러므로, 꼭 필요한 곳에 사용하는 것이 좋고, 그렇게 하라고 goto 문이 있다고 생각합니다.

Orion Project : http://orionids.org

vacancy의 이미지

Java 등에서는 다중 루프를 빠져나갈 수 있는 break문을 제공하죠.

goto문이 많이 들어간 코드는 눈으로 따라가며 보기엔 정말 좋지 않은듯요.
goto가 없다고 생각하고 코딩하는 경우 더 깔끔하게 코드가 나오지 않는지요;
습관의 문제.

nthroot의 이미지

Goto를 안쓰는것을 원칙으로..프로그램을 하구요.
코드 중간에 레이블 걸린것 보기 안좋다고 생각되거든요. 코드가 이해하기 어려운건 아닌데.. 코드 구조가 흐트러진다고 여기기 때문에..

팀프로젝트할때 남의 코드에 GOTO가 있으면 저도 같이 써줍니다. -_-;; (놀부 심보..)

------식은이 처------
길이 끝나는 저기엔 아무 것도 없어요. 희망이고 나발이고 아무 것도 없어.

소타의 이미지

다중 루프나 루프 안의 switch 문을 빠져나올 때만 씁니다.. -.-;
아니 그럼 이럴 때에는 당췌 어떻게 해야 합니까? -.-;;
C에서요..

sanghyune의 이미지

one 1 ~ 100{
two 1 ~ 100{
three 1 ~ 100{
if three == 33 {
one = 100;
two = 100;
break;
}
}
}
}

여기서 goto문을 쓰고 안쓰고의 차이는
루프에 쓰이는 변수를 다른용도로 쓰느냐 안쓰느냐의 차이뿐이겟지요.
(아마도 변수하나 더 써줘야한다는 귀찮은일이 생기겟지요)

atie의 이미지

93년 이후로는 goto를 쓴 적이 없구나 하고 생각이 드네요. 변수의 조건에 따라 루프를 들어가거나 나오고, 무조건 루프를 돌때는 정해진 만큼만 돌아야 하니 goto를 쓸 일이 없었던 것 같군요.

----
I paint objects as I think them, not as I see them.
atie's minipage

Darkcircle의 이미지

goto문이 나쁘다고 해서 데체적으로 쓰지 말라는 쪽으로 권고가 되고 있지만,
goto문을 필요한 경우에서라도 무조건 안 쓰게 되면
사실 goto문을 만든 의도마저 묵살될 수도 있지요 :)
goto문을 만든 어떤 목적이 있을거라 생각합니다.

단순히 코딩하기 귀찮아서 goto문을 쓰는것 이외에도 이유를 찾다보면
goto문이 아주 "꼭" 필요한 경우가 드물게 있을거라는거죠 :)
어떤 경우에서라도 goto문이 무조건 필요악으로 치부되어버린다면
아마 C 표준안에서 goto문에 대한 내용이 삭제되었어야 할지도 모릅니다.
쓰지도 않을 표준은 있어봤자 존재 여부자체로도 필요악이기 때문입니다.

---------------------------------------------------------------
폐인이 되자 (/ㅂ/)

Rica의 이미지

제 코드의 모든 goto 레이블은 out_of_{.*}_loop: 이랍니다. :)

madhatter의 이미지

어셈의 jump나 C의 goto나...
goto는 객체지향이 대세를 이루면서 사장된 거 아닌가 합니다. C++이 대세 이루기 전엔 goto 많이 썼거든요. (Basic에서)

indie의 이미지

저는 함수내 리턴용으로 사용합니다.
그외에는 별로 써본일이 없는것 같네요.

집에나 갈까?

envia의 이미지

소타 wrote:
다중 루프나 루프 안의 switch 문을 빠져나올 때만 씁니다.. -.-;
아니 그럼 이럴 때에는 당췌 어떻게 해야 합니까? -.-;;
C에서요..

변수 하나 더 써 주시면 됩니다. (조금 귀찮기는 하지요.)

----

It is essential, if man is not to be compelled to have recourse, as a last resort, to rebellion against tyranny and oppression, that human rights should be protected by the rule of law.
[Universal Declaration of Human Rights]

체스맨의 이미지

envia wrote:
소타 wrote:
다중 루프나 루프 안의 switch 문을 빠져나올 때만 씁니다.. -.-;
아니 그럼 이럴 때에는 당췌 어떻게 해야 합니까? -.-;;
C에서요..

변수 하나 더 써 주시면 됩니다. (조금 귀찮기는 하지요.)

중요한 문제는 귀찮다는 것이 아니라, 루프 빠져나오려고 변수 쓰면 goto 보다 더 복잡해지고, goto 사용하는 경우 없어도 될 불필요한 루틴이 추가된다는 점입니다.

상황에 따라서는 정 goto 가 싫으면 함수로 잘 묶어서 리턴해버리는 방법도 있습니다.

Orion Project : http://orionids.org

dhunter의 이미지

저는 goto 를 basic 때는 한참 썼는데 C/PHP 와서는 이 언어에 goto 가 지원된다는 사실조차 몰랐습니다 -__;

from bzImage
It's blue paper

bugslife의 이미지

존재는 알았지만 하도 사용하지 않는것을 권고 받다보니..
코딩시에 아예 까먹어 버렸군요.

그러고보니 전역변수는 편의(?)에 의해 심심치않게 사용하는데..
goto는 아예 사용을 안하는군요.

뭐.. 이젠 필요성도 느끼지 않지만요.

함수화.. 함수화..

어느순간부터인가 하루살이의 하루를 알고싶다.

youlsa의 이미지

exception을 지원하지 않는 C에서는 다중 루프 등을 빠져나올때 goto만한게 없습니다. 리눅스 커널에서도 try catch 쓰듯이 goto를 쓰고 있는걸 볼 수 있습니다.

=-=-=-=-=-=-=-=-=
http://youlsa.com

버그소년의 이미지

흠.. 이 글을 보고 작업중인 코드를 확인해보니

한군데에 goto를 사용했네요.. ^^;

머리가 나빠서 뭘썼나 기억도 잘 못해서리..

전 필요하다고 생각되면 가차없이(?) 씁니다.

가끔은 밥을 굶어도 살 수 있다.

pynoos의 이미지

함수를 70줄 이내에 작성하는 것을 습관화하고,
loop와 비교문의 깊이를 3 이하로 줄이도록 연습하다보면,
상당수 goto 문을 안쓰고도 깔끔하게 나옵니다.

그리고, kernel 코드의 코딩 스타일과 일반 어플리케이션 코드의 코딩스타일을 비교하는 것은 좋지 않습니다.

kernel은 그야말로 속도를 위해 과감히 버리는 것들이 많기 때문에, goto도 그만큼 속도를 위해서라면 사용하기 마련입니다.

이렇게 말하는 저도 goto를 안쓰는 것은 아닙니다. :)

체스맨의 이미지

"goto문은 절대로 쓰지 마라"

이 말의 근원은, 과거 베이식이나 포트란 처럼 제어 구문이 발달되어 있지 않은 언어로부터, 제어 구문이 잘 발달된 C 로 넘어오는 과정에서 프로그래머들이 과거의 타성에 젖어 goto 문을 남발하는 상황에서 나온 말이라고 생각되는데요.

일례로 Numerical Recipe 의 C 버젼은 포트란 소스에 대한 직역본으로 수많은 goto 문을 남발하고 있습니다. 특히 공학용 교재의 수치해석 C 소스들에 goto 문이 많은 것을 볼 수 있습니다. 기존 포트란 코드의 영향일 것인데요...

이런 상황이라면 C 개발자들이 히스테리컬하게 '절대 쓰지 마라' 라는 말을 할 수 밖에 없었을 겁니다. 하지만, 현재 상황에서는 이렇게 부정적인 말보다는, "꼭 필요한 곳에만 써라" 정도로 바뀌어야 하지 않을까 생각합니다. 구전되어온 이 말이 뇌리에 박혀서 goto 를 필요해서 쓰면서도 항상 꺼려하는 게 좋지 않게 생각되네요.

Orion Project : http://orionids.org

kall의 이미지

http://www.zdnet.co.kr/techupdate/lecture/os/0,39024998,10060491,00.htm

Quote:
지난 2월 11일에는 goto 논쟁의 발화점이라 할 만한 다익스트라(Edsger W. Dijkstra)의 논문 「Go To Statement Considered Harmful」과 관련 글을 읽고, 그에 대한 토론을 했다.

http://www.acm.org/classics/oct95/

----
자신을 이길 수 있는자는
무슨짓이든 할수있다..
즉..무서운 넘이란 말이지 ^-_-^
나? 아직 멀었지 ㅠㅠ

서지훈의 이미지

잘 쓰면 藥, 잘 못 쓰면 毒.

절대로 못쓸 넘은 아니져^^

근데... 개인적으로는 제 코드에 goto 문을 써본적은 없습니다.

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

#include <com.h> <C2H5OH.h> <woman.h>
do { if (com) hacking(); if (money) drinking(); if (women) loving(); } while (1);

saxboy의 이미지

Dijkstra가 등장했으니 공식처럼 Knuth 도 등장해야겠지요?

Structured Programming with goto Statements (Computing Surveys 6 (4), 261-301, December 1974)

온라인으로 풀버전이 있으면 참 좋겠는데, 찾질 못하겠군요. :<

어디까지나 제 경우이지만, 저는 return 을 한 곳으로 통일하기 위해서 goto 를 즐겨 사용합니다. :-P

kane의 이미지

풀버전으로 추정되는 문서를 찾았습니다.
강의자료로 올려놓은 모양이더군요.

http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf

zepinos의 이미지

babjo87 wrote:
흔히 프로그래밍 공부하면서 가장 자주 듣는 말중 하나가

"goto문은 절대로 쓰지 마라" 일겁니다.


저의 경우 절대로가 아니라 가급적 혹은 정말 필요한 경우가 아니라면...이라고 들었습니다.
fairycat의 이미지

운영체제 관점으로 보자면..
"Locality를 해치기 때문에 Goto문을 쓰지 말아라"고 하는 것을 들었습니다.

시각적, 공간적으로 자주 쓰이는 부분이 계속 쓰인다는 것인데.. 운영체제는
이러한 Locality를 활용할수 있도록 만들어져있기 때문에 Goto 문처럼 다른
Local로 건너뛰어버리는 식의 코드는 이러한 Locality를 해칠 수 있다는 뜻이
지요. 프로그램적으로만 해석하자면..

이러한 부분을 놓칠수 있지 않을까 생각됩니다만..

가이: 리여.. 확실히 너는 네지와는 다르다
록리: 위로라면 집어치세요..
가이: 위로같은게 아니다 ! 너는 네지와는 다르게 천재도 아니고 재능도 없다 하지만 너는 노력의 천재다..

- 나루토 <키시모토마사시>

cppig1995의 이미지

if(p == q) { ... } else { ... }의 경우는 어떨까요?
역시 조건문 체크해서 점프(=goto)하지 않나요?



절망으로 코딩하고 희망으로 디버깅하자.

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

creativeidler의 이미지

<Quote>goto 문이 반드시 쓰지 말아야 할 것이라면, 아예 그것이 존재하지 않았겠죠. </Quote>

그래서 최근에 나온 고급 언어에는 없습니다. C에는 그냥 호환성을 위해 남아 있다고 보는 게 맞겠죠.

체스맨의 이미지

creativeidler wrote:
<Quote>goto 문이 반드시 쓰지 말아야 할 것이라면, 아예 그것이 존재하지 않았겠죠. </Quote>

그래서 최근에 나온 고급 언어에는 없습니다. C에는 그냥 호환성을 위해 남아 있다고 보는 게 맞겠죠.

다음과 같은 경우 goto 문을 없애고 싶다면 어떻게 해야 할까요?

if( case_a ) {
	....; /* do something A */
	goto l_case_b;
}

if( case_b )
{
	l_case_b:
	...; /* do something B */
}

1. goto l_case_b 대신 case_b 가 true 가 되도록 무언가 할 수 있겠죠.

if( case_a ) {
	....; /* do something A */
	...; /* make case_b to true */
}

2. 또는 if 를 한번 더 쓸 수도 있을 겁니다.

if( case_a || case_b )
{
	if( case_a ) {
		....; /* do something A */
	}
	...; /* do something B */
}

3. 또는 함수로 묶을 수도 있겠죠.

if( case_a ) {
	....; /* do something A */
	do_something_B();
}
else if( case_b )
{
	do_something_B();
}

등등의 방법이 있을 것인데 모든 방법이 미약하더라도 goto 를 쓸 때보다 조금의 인스트럭션을 더 쓰기 때문에 택하기 싫고, 예시된 코드처럼 goto 가 가독성을 저해하거나 스파게티를 만들지 않는 상황에서는 무엇을 써야 할까요?

goto 가 단지 호환성을 위해 남아있다고 볼 수는 없다고 생각합니다.

Orion Project : http://orionids.org

gimmesilver의 이미지

체스맨 wrote:

다음과 같은 경우 goto 문을 없애고 싶다면 어떻게 해야 할까요?

if( case_a ) {
	....; /* do something A */
	goto l_case_b;
}

if( case_b )
{
	l_case_b:
	...; /* do something B */
}

위에 제시된 예제는 아무생각없이 타이핑하기에는 편할지 모르지만 결코 좋은 코드라 생각되지 않습니다.
첫째, 결국 위의 코드가 하고자 하는 목적은 'case_a일때는 'do something A와 do something B에 있는 루틴을 실행하고 case_b일때는 do something B만 시행하라' 입니다.
그렇다면 그러한 알고리즘이 나타날 수 있도록 코드를 작성하는 것이 좋습니다. 하지만 위의 코드는 그러한 workflow를 명시적으로 드러내지 못하고 있습니다.
차라리

if (case_a || case_b)
    {
    if (case_a)
        do_something_only_A();

    do_something_A_and_B();
    }

혹은

if (case_a)
    {
    do_something_only_A();
    do _something_A_and_B();
    }

if (case_b)
    {
    do_something_A_and_B();
    }

이게 더 좋다고 생각합니다. 타이핑할 게 좀 더 많아 지고 if문이 두개가 사용되긴 하지만 실제 원하는 알고리즘과 코드가 일치하므로 가독성 면에서나 알고리즘 검증에 더 유리합니다.

또한 만약 차후 기능이 변경되어서 'case_a일때 do something A를 수행하고 do something B 이후에 do something C를 수행하는 과정이 더 추가되어야 하고 case_b일때는 원래대로 놔두어야 하는 상황(do something B만 수행)이 발생한다면 또는 case_b일때는 do something D를 추가해야 한다면...goto구문은 코드를 수정하는데 걸림돌이 되고 맙니다.

goto는 가독성 면에서나 알고리즘의 이해에 안좋은 점도 있지만 유연성이 떨어지므로 유지 보수 시 코드 수정에도 문제점이 있습니다.

Quote:
모든 방법이 미약하더라도 goto 를 쓸 때보다 조금의 인스트럭션을 더 쓰기 때문에 택하기 싫고, 예시된 코드처럼 goto 가 가독성을 저해하거나 스파게티를 만들지 않는 상황에서는 무엇을 써야 할까요?

goto 가 단지 호환성을 위해 남아있다고 볼 수는 없다고 생각합니다.

글쎄요...인스트럭션을 조금 더쓰기 싫어서 즉, goto를 쓰는게 한순간 편하다고 해서 쓴다는 것은 문제가 있다고 봅니다...게다가 지금 당장은 저 코드가 문제가 없다 하더라도 훗날 기능 추가나 변경 등의 유지 보수 단계에서 이 코드가 씨앗이 되어 스파게티가 되지 않는다고 어떻게 장담할 수 있습니까?
리펙토링이나 디자인 패턴과 같은 것들이 요즘 사람들에게 많은 이슈가 되고 있는 것은 이제는 현재 구현할 기능을 얼마나 빨리 쉽게 만드느냐 보다 앞으로 이 코드를 가지고 얼마나 오래 울거먹을 수 있느냐하는 것이 중요하기 때문입니다...
goto는 코드의 재사용이 사실상 거의 불가능하다며 알고리즘을 제대로 반영하지 못하는 등의 단점이 있습니다.

------------------------
http://agbird.egloos.com

angpoo의 이미지

체스맨 wrote:
다음과 같은 경우 goto 문을 없애고 싶다면 어떻게 해야 할까요?

if( case_a ) {
	....; /* do something A */
	goto l_case_b;
}

if( case_b )
{
	l_case_b:
	...; /* do something B */
}


switch(case1) {
  case a:
    /* do something A */
  case b:
    /* do something B */
  break;
}

복잡한 조건이면
if (case_a || case_b)
  switch((case_a)) {
    case TRUE:
      /* do something A */
    case FALSE:
      /* do something B */
    break;
  }

실제로는 if문을 중첩해서 쓰게 될 것 같네요.

체스맨의 이미지

Agbird wrote:

위에 제시된 예제는 아무생각없이 타이핑하기에는 편할지 모르지만 결코 좋은 코드라 생각되지 않습니다.

"좋은 코드" 라는 포괄적인 얘기를 하자면, 제가 제시한 1, 2, 3 이 "상황에 따라" 좋은 코드가 될 수 있다고 말씀 드릴 수 있겠죠. 그리고, 물론 goto 를 쓴 코드도 상황에 따라 좋은 코드가 될 수 있다고 말씀드릴 수 있습니다.

Agbird wrote:

인스트럭션을 조금 더쓰기 싫어서 즉, goto를 쓰는게 한순간 편하다고 해서 쓴다는 것은 문제가 있다고 봅니다.

"인스트럭션을 조금 더 쓰기 싫어서" 와 "goto를 쓰는게 한순간 편하다고" 라는 두 문장은, "즉" 으로 연결될 수 있는 동급의 문장이 아닙니다. goto 를 쓴 것이 인스트럭션을 (조금이나마) 줄이려는 게 목적이었다면, 한순간 편하다는 것과는 매우 다른 이유죠.

Quote:

리펙토링이나 디자인 패턴과 같은 것들이 요즘 사람들에게 많은 이슈가 되고 있는 것은 이제는 현재 구현할 기능을 얼마나 빨리 쉽게 만드느냐 보다 앞으로 이 코드를 가지고 얼마나 오래 울거먹을 수 있느냐하는 것이 중요하기 때문입니다...

말씀하신 이슈가 되는 바에 대해서는 저도 중요하다고 생각합니다. 제가 goto 를 주장하는 것이 말씀하는 이슈들에 역행하는 것으로 오해하진 않으셨으면 합니다.

Quote:

goto는 코드의 재사용이 사실상 거의 불가능하다며 알고리즘을 제대로 반영하지 못하는 등의 단점이 있습니다.

동의 할 수 없습니다. 이유는 이전의 제 글이나, goto 를 옹호하는 입장을 가지신 분들의 의견에 이미 있을 것이고, 코드 재사용이 불가능하다거나 알고리즘이 제대로 반영되지 않는 단점 같은 것은 saxboy 님께서 말씀하신
Structured Programming with goto Statements
이 글로 해결될 수 있을 겁니다.

'상황에 따라' 라고 말씀 드린데에 유념해 주세요. 필요한 상황이 있기 때문에 호환성을 위해 남아있는 것이 아니라고 말씀드린 겁니다.

* 좀 더 읽어보니, 저는 인스트럭션을 조금 더 쓰기 싫어서라고 말씀드린게 속도 최적화 관점에서 말씀드린 것인데 "인스트럭션을 조금 더쓰기 싫어서 즉, goto를 쓰는게 한순간 편하다고 해서 쓴다는 것은 문제가 있다고 봅니다." 이런 의미로 오해하신 게 아닌가 생각되네요.

Orion Project : http://orionids.org

segfault의 이미지

명예의 전당에 등록되었군요.

영광입니다 :)

afsadfsaf의 이미지

goto를 쓰지 말라 해서 안쓴다기 보다는 그다지 쓸 일이 안생기더군요.

제 생각엔 생각하는 스타일 자체가 goto 랑 if/else/for 중첩과는 조금 다르다고 생각합니다.

그래서 주로 한 스타일로만 생각하는게 편해서 아예 다른 스타일로는 생각할 여력도 없더군요..

뭐 사실 if else for 중첩도 심해지면 정말 이해하기 힘듭니다. 뭐 제가 코드를 잘못 짜서 그럴 수도 있겠지만 case 와 그 안의 if else 로 파서를 구현했는데 정말 죽을 맛이었죠.(직접 만든 IRC클라이언트의 mIRC의 컬러 루틴 파서였습니다만..)

goto로도 얼마든지 간단하고 이해 가능하게 짤 수 있을테고, 중첩문으로도 얼마든지 햇갈리게 못짤 수 있다고 봅니다.

goto를 쓰지 말라! 에 내포된 진짜 이야기는, 명령어의 문제라기 보다는 프로그래밍을 이해하기 어렵게만 안짜면 된다는 이야기겠죠.

음 하지만 역시 goto를 쓰면 OpenGL의 스펙 문서의 "3.3.1에 무슨무슨 디테일이 나와있습니다." 이런식으로 나와있는것 처럼 정말 귀찮은 코드가 될 가능성이 높겠지요.

뭔가 스크롤을 바꾼다는건 이런거랑 비슷한지 않나요? "다른 곳으로 갔다가 온다." 사무실 A 에서도 할 수 있는데 사무실 B 사무실 C~Z 옮겨가며 하면 정말 귀찮죠. 중복되는 내용이 있더라도 OpenGL 문서가 "3.3.1에 좀 더 디테일이 써져 있습니다" 라는 식이 아닌, 그자리에서 모두 중복될지라도 디테일을 자세히 설명했다면 좀 더 보기 좋았을 거란 생각이 듭니다. MSDN의 OpenGL 문서는 그렇게 되어 있지요. 뭐 물론 별반 차이 없다고 보시는 분들도 계시겠지만.. 가끔 힘든일을 하다보면 사소한 일에도 짜증이 나는 법이라서;;

뭐 물론 AcroRead 의 "뒤로가기" 기능에 익숙해지고 나면 이런 것도 불편한 건 못 느끼지만요. 오히려 중복되는 내용이 많아서 짜증나는 경우도 있겠죠.

뭐 결국 GOTO문의 문제는 "익숙하지 않은 할 일"이 너무 많아지기에 짜증나는 경우랄까요.. :$

L-System

gimmesilver의 이미지

체스맨 wrote:

"좋은 코드" 라는 포괄적인 얘기를 하자면, 제가 제시한 1, 2, 3 이 "상황에 따라" 좋은 코드가 될 수 있다고 말씀 드릴 수 있겠죠. 그리고, 물론 goto 를 쓴 코드도 상황에 따라 좋은 코드가 될 수 있다고 말씀드릴 수 있습니다.

그렇겠죠. 어디에서나 특수한 상황은 존재하는 법이니까요... :)

Quote:

"인스트럭션을 조금 더 쓰기 싫어서" 와 "goto를 쓰는게 한순간 편하다고" 라는 두 문장은, "즉" 으로 연결될 수 있는 동급의 문장이 아닙니다. goto 를 쓴 것이 인스트럭션을 (조금이나마) 줄이려는 게 목적이었다면, 한순간 편하다는 것과는 매우 다른 이유죠.

Quote:
'상황에 따라' 라고 말씀 드린데에 유념해 주세요. 필요한 상황이 있기 때문에 호환성을 위해 남아있는 것이 아니라고 말씀드린 겁니다.

* 좀 더 읽어보니, 저는 인스트럭션을 조금 더 쓰기 싫어서라고 말씀드린게 속도 최적화 관점에서 말씀드린 것인데 "인스트럭션을 조금 더쓰기 싫어서 즉, goto를 쓰는게 한순간 편하다고 해서 쓴다는 것은 문제가 있다고 봅니다." 이런 의미로 오해하신 게 아닌가 생각되네요.

제가 말씀드린 goto를 쓰는게 한순간 편하다라고 한것은 인스트럭션을 '조금이나마' 줄여서 속도를 최적화하려고 goto를 사용하겠다는 것 자체가 너무 쉽게 문제를 풀어가려는 것이 아닌가 하고 지적한 것입니다.
물론 정말 아주 특수한 경우 그런 몇몇의 마이크로 레벨의 명령어를 줄여주는 것이 정말 중요한 상황이 있을 수도 있을지 모르겠습니다... :roll:
그러나 우리가 일반적으로 개발을 하는 상황에서 goto를 써서 속도를 최적화해야 할 정도로 그렇게 열악한 조건을 가지는 경우는 거의 없습니다.
대개는 프로그램의 알고리즘이나 자료구조를 바꿔줌으로써 얼마든지 더 큰 최적화가 가능합니다.(programming perals에 이런 내용이 잘 나와있죠...)

만약 정말 그런 goto를 써야 하는 어쩔 수 없이 특수한 상황이 있으므로 goto가 필요하다고 주장하시려면 그런 상황을 예시해 주셔야 합니다...위에 제시한 예는 goto를 옹호하기에는 좋은 예가 아닌 것 같습니다...차라리 몇몇 firmware나 embeded system에서는 메모리 부족등의 열악한 환경 때문에 어쩔수 없이 goto를 사용한다...정도가 더 설득력이 있을 것 같습니다...

Quote:
동의 할 수 없습니다. 이유는 이전의 제 글이나, goto 를 옹호하는 입장을 가지신 분들의 의견에 이미 있을 것이고, 코드 재사용이 불가능하다거나 알고리즘이 제대로 반영되지 않는 단점 같은 것은 saxboy 님께서 말씀하신
Structured Programming with goto Statements
이 글로 해결될 수 있을 겁니다.

그 글을 읽어 본적이 없어서 뭐라 말씀드릴 수가 없네요...

------------------------
http://agbird.egloos.com

체스맨의 이미지

C 의 goto 가 단지 호환성을 이유로 남아있다는 말씀에 대한 반론이었고, 단편적인 예였습니다. 그러나 실재 발생할 수 있는 상황이고 발생했던 상황입니다. 그냥 예제를 위한 예제는 아니었구요.

최근의 고급언어들이 다중 루프를 빠져나오거나, 예외 처리를 지원하는데, C 는 그런 것이 없어서 어쩔 수 없이 goto 가 있는 게 아니냐라는 주장에 대한 반론이지요.

goto 를 문제를 쉽게 풀기 위한 목적으로 사용한 개발자라면, 그것은 goto 를 남용하는 상황이겠죠. 저도 이것은 반대입니다. '최선'이라는 관점에서 사용해야 한다는 것입니다.

속도 최적화는 열악한 환경이기 때문에 하는 것이 아니라, 더 빠른 것을 원하기 때문에 하는 것입니다. 하나의 예를 원하신다면 소프트웨어 렌더러를 만들때 goto 를 써서라도 최적화합니다. 이것은 열악한 환경이기 때문에 사용되는 goto 가 아닙니다. 삼각형 스캔라인 렌더링 루틴에서 인스트럭션 하나를 줄이는 것은 전체 그래픽 렌더링 성능에 적지 않은 영향을 미칩니다. 이것은 알고리즘이나 자료 구조 최적화로 해결할 수 없는 문제 입니다.

물론 알고리즘과 자료 구조에 의한 최적화가 매우 중요한 것이 사실이고 이것은 반론의 여지가 없습니다. 그러나 좋은 알고리즘과 자료구조가 적용된 이후의 최적화는 인스트럭션을 줄이는 것입니다.

최근에 실시간 하드웨어 렌더링이 비약적으로 발전했지만, 여전히 실사에 가까운 화질을 낼 수 있는 비실시간 알고리즘은 하드웨어에 적용되지 않습니다.

Orion Project : http://orionids.org

inhosens의 이미지

w12ard wrote:
운영체제 관점으로 보자면..
"Locality를 해치기 때문에 Goto문을 쓰지 말아라"고 하는 것을 들었습니다.

시각적, 공간적으로 자주 쓰이는 부분이 계속 쓰인다는 것인데.. 운영체제는
이러한 Locality를 활용할수 있도록 만들어져있기 때문에 Goto 문처럼 다른
Local로 건너뛰어버리는 식의 코드는 이러한 Locality를 해칠 수 있다는 뜻이
지요. 프로그램적으로만 해석하자면..

이러한 부분을 놓칠수 있지 않을까 생각됩니다만..

운영체제의 관점에서 보면 펑션콜이나 일부 루프들도 goto와 다를게 없이 해석되지 않나요?
cache의 효용성에 대한 얘기는 goto문만 가지고 얘기할 문제는 아닐 듯 싶습니다.

valor의 이미지

     if (malloc1 == error)
          goto error1
     if (malloc2 == error)
          goto error2
     if (malloc3 == error)
          goto error3
     Do_Job
     return OK

error3:
     free3
error2:
     free2
error1:
     free1
     return ERROR

단계적으로 resource를 받아서 처리하는 부분에서 중간에 하나의 resource를 얻지 못해서 이전에 받은 resource를 모두 해제해는 경우라면 goto를 쓰는게 가장 좋지않을까 합니다.

최종호의 이미지

valor wrote:
     if (malloc1 == error)
          goto error1
     if (malloc2 == error)
          goto error2
     if (malloc3 == error)
          goto error3
     Do_Job
     return OK

error3:
     free3
error2:
     free2
error1:
     free1
     return ERROR

단계적으로 resource를 받아서 처리하는 부분에서 중간에 하나의 resource를 얻지 못해서 이전에 받은 resource를 모두 해제해는 경우라면 goto를 쓰는게 가장 좋지않을까 합니다.

저도 이런 비슷한 코드를 사용합니다.
이렇지 않은 경우에 자원 해제시켜주는 부분에서 코드의 중복이 발생합니다.
poor man's (person's? language's?) exception handling construct 정도로 생각하는데,
free1, free2, free3 호출하는 부분을 하나의 함수로 뽑아서 하나만 부르기에는 응집도가 떨어지는 것 같아보이고,
가끔 전달해야 할 context도 제법 있는 경우가 있어서
goto 없애기보다는 single entry, single exit 쪽을 취하는 경우가 많습니다.

이런 전차로, 제 goto 문의 레이블은 항상
cleanup:
입니다.

error1, error2, error3 와 같이 레이블을 쓰기보다는
file1_opened,
list_allocated
등의 flag 변수를 두어서 그걸 검사하죠.

보통은 함수 안에서 자원들을 할당하고, 함수를 나가기 전에 사용한 자원들을
해제해야 하기 때문에 정상적인 수행도 cleanup: 쪽의 루틴들을 탑니다.

gimmesilver의 이미지

valor wrote:
     if (malloc1 == error)
          goto error1
     if (malloc2 == error)
          goto error2
     if (malloc3 == error)
          goto error3
     Do_Job
     return OK

error3:
     free3
error2:
     free2
error1:
     free1
     return ERROR

단계적으로 resource를 받아서 처리하는 부분에서 중간에 하나의 resource를 얻지 못해서 이전에 받은 resource를 모두 해제해는 경우라면 goto를 쓰는게 가장 좋지않을까 합니다.

저는 그러한 경우 아래와 같이 작성합니다...

int i = ERROR;
if (malloc1 != error)
    {
    if (malloc2 != error)
        {
        if (malloc3 != error)
            {
            Do_job
            i = OK;
            free3
            }

        free2
        }

    free1
    }

return i;

예전 devpia에서도 이 스타일에 대해서 글을 쓴적이 있는데 예상대로 중첩 if문에 대한 반발이 심하더군요... 8)
하지만 그건 이런 중첩 if문 스타일에 익숙하지 않기 때문이고 이런 것에 익숙해 진다면 goto를 사용하는 것보다 유지 보수나 리펙토링에 훨씬 유리한 코드라 생각합니다.
적어도 제 경험상으로는 그렇습니다... :wink:

------------------------
http://agbird.egloos.com

bugiii의 이미지

Agbird wrote:
valor wrote:
     if (malloc1 == error)
          goto error1
     if (malloc2 == error)
          goto error2
     if (malloc3 == error)
          goto error3
     Do_Job
     return OK

error3:
     free3
error2:
     free2
error1:
     free1
     return ERROR

단계적으로 resource를 받아서 처리하는 부분에서 중간에 하나의 resource를 얻지 못해서 이전에 받은 resource를 모두 해제해는 경우라면 goto를 쓰는게 가장 좋지않을까 합니다.

저는 그러한 경우 아래와 같이 작성합니다...

int i = ERROR;
if (malloc1 != error)
    {
    if (malloc2 != error)
        {
        if (malloc3 != error)
            {
            Do_job
            i = OK;
            free3
            }

        free2
        }

    free1
    }

return i;

예전 devpia에서도 이 스타일에 대해서 글을 쓴적이 있는데 예상대로 중첩 if문에 대한 반발이 심하더군요... 8)
하지만 그건 이런 중첩 if문 스타일에 익숙하지 않기 때문이고 이런 것에 익숙해 진다면 goto를 사용하는 것보다 유지 보수나 리펙토링에 훨씬 유리한 코드라 생각합니다.
적어도 제 경험상으로는 그렇습니다... :wink:

만약 사용하는 언어가 C++ 이고 위와 같은 경우라면, 저는 더이상 두가지 형태 모두 사용하지 않습니다.

ScopeGuard 를 사용합니다.

http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/alexandr.htm

꼭 추천하고 싶은 프로그래밍 기법입니다.

gimmesilver의 이미지

Quote:

만약 사용하는 언어가 C++ 이고 위와 같은 경우라면, 저는 더이상 두가지 형태 모두 사용하지 않습니다.

ScopeGuard 를 사용합니다.

http://www.cuj.com/documents/s=8000/cujcexp1812alexandr/alexandr.htm

꼭 추천하고 싶은 프로그래밍 기법입니다.

와우! 역시 andrei...라는 말밖에는...
마지막에 RefHolder class에 대한 글에 가서는 완전히 두손 두발 다 들고 말았습니다... :shock:
정말 좋은 것 배웠네요... :wink:

------------------------
http://agbird.egloos.com

creativeidler의 이미지

if( case_a ) { 
   ....; /* do something A */ 
   goto l_case_b; 
} 

if( case_b ) 
{ 
   l_case_b: 
   ...; /* do something B */ 
} 

이것만으로는 goto를 써야할 이유로 보이지 않습니다. case_a와 case_b를 어떻게 조합하느냐, 그리고 A와 B를 어떻게 조합하느냐에 따라 얼마든지 해결할 수 있는 문제죠. 그리고, 굳이 억지로 풀고자 한다해도 속도에는 영향 없이 goto 제거할 수 있습니다.

if( case_a ) { 
   ....; /* do something A */ 
   ...; /* do something B */ 
} 
else if( case_b ) 
{ 
   l_case_b: 
   ...; /* do something B */ 
} 

이렇게 하면 되겠죠. 코드 중복이야 extract method 하면 될 테구요. 아니면 메쏘드 중간에서 return을 적절히 활용할 수도 있을 테구요. 게다가 이 코드는 위의 goto 코드에 비해 조건과 행위가 한 눈에 매핑이 된다는 결정적인 장점이 있죠. 그에 비해 잃는 것은 아주 작죠.

또한, 저런 종류의 goto나 if 중복 등의 문제는 컴파일러가 최적화를 어떻게 하느냐에 따라 상당히 달라질 수 있습니다. goto는 컴파일러가 바로 점프로 바꾸는 반면, if의 중복 같은 건 경우에 따라 상당히 많이 최적화될 수 있습니다. if 안에 조건식의 복잡도에 따라 if 두번 쓰는 게 더 나을 수도 있다는 얘기죠.

그리고, 현실적으로 if 문 하나 줄이고 메쏘드 호출 하나 줄이자고 goto를 쓰는 게 좋다는 주장은 요즘의 퍼포먼스 이론과 상당한 거리가 있습니다. 퍼포먼스는 눈에 보이는 모든 성능 요인들을 튜닝하는 게 아닙니다. 그건 공학이 아니죠. 일단 가독성 높고 이해하기 쉬운 코드를 써놓고 나서 속도 결정 요인을 하나하나 찾으면서 튜닝하는 것이 바람직합니다. 이른바 lazy optimization and early profiling이죠. 특수한 영역에서는 고수준의 최적화가 필요할 수 있다는 주장, 물론 옳습니다. 그러나, 정확히 어떤 분야가 그렇습니까? 그런 분야에 일하는 분은 여기 오는 분 중 0.01%도 안될 겁니다. OS, 컴파일러, 임베디드, 3D, 공학 계산 분야까지도 다 해당사항이 없습니다. 아마 리얼 타임 소프트웨어 중에서도 우주선이나 잠수함처럼 아주 고수준의 공학적 계산을 아주 빠른 시간 내에 해야하는 그런 경우에나 적용될 가능성이 있겠죠. 실제 PC에서 돌아가는 애플리케이션에는 그런 경우는 없다고 봐도 과언이 아닐 겁니다. 요즘 화려한 3D 그래픽 게임들도 다 C보다 한참 느리다는 C++ 쓰고 온갖 객체 지향 기술 다 쓰면서도 잘 돌아갑니다.

C는 물론 최신 객체지향 언어들처럼 예외 처리 구문이 있는 것도 아니고 다형성이 되는 것도 아니라서 goto를 쓰고 싶은 생각이 들 때도 있을 겁니다. 그렇지만 대부분의 경우는 단지 함수를 적절히 리팩토링하는 것만으로도 goto의 사용 없이 성능을 거의 떨어뜨리지 않으면서 가독성 좋은 코드를 만들어낼 수 있습니다.

체스맨의 이미지

말씀하신 것들이 대부분 옳습니다. 그리고 그런 것이 틀리다고 얘기하는 것이 아니라는 것을 미리 말씀드린 것 같구요. 관점과 그 범위의 차이에 의해 다른 의견이 나오는 것으로 생각됩니다. 예를 들어

Quote:

요즘 화려한 3D 그래픽 게임들도 다 C보다 한참 느리다는 C++ 쓰고 온갖 객체 지향 기술 다 쓰면서도 잘 돌아갑니다.

일단, 그 이유는 게임 성능의 80~90%를 점유하는 그래픽 렌더링 부분이 하드웨어에서 지원되는 시대이기 때문입니다. 그래서 저는 소프트웨어 렌더러를 말씀드렸고, 하드웨어에서 지원되지 못하는 렌더링 기법이 아직 많다고 말씀드렸지요.

게임의 성능과 goto 를 논하기엔 게임은 너무 범주가 커서, goto 를 사용하냐 마느냐는 매우 편협한 하나의 상황에 해당합니다. 게임 하나를 놓고봐도, 온갖 객체 지향 기술을 적용할 수 있는 부분이 있고, 그것이 유리한 부분이 있는가 하면, 그렇지 않은 부분도 있습니다.

말씀하신 다른 예들에 대해서도 저는 관점과 범주에 서로 차이가 있다고 봅니다.

그래서, 아주 미세한 차이로 여겨지는 다음 두 주장이 오고가는데,

Quote:

goto 를 아예 쓰지 말아야 한다.
goto는 꼭 필요한 부분에만 써야한다.

저는 두번째를 주장하는 것이며, 사실 두 주장의 차이는 크지 않습니다. 어떠한 최신 이론을 적용하든, 저 두 주장에 대한 판단은 결국 "상황에 따라" 개발자 가 하는 것이라고 말씀드리는 것까지로 제 주장을 마치고 싶습니다. 저 미세한 차이는 좁혀지지 않는 것이라 생각하고, 좁힐 필요가 없다고 보여지네요.

Orion Project : http://orionids.org

ironiris의 이미지

C언어에서 goto 는 ++ 처럼 어셈블리명령과 1:1로 매칭될수 있는 명령아니던가요? 속도를 위해서라면 충분히 쓰고도 남을 명령이라고 생각됩니다.
goto명령을 써서 스파게티코드가 된다면 분명히 문제가 있지만 goto명령을 써서 코드가 간단해지고 빨라진다면 할만하겠죠?
특히 중첩 for, while문에서 몇번째 for인지 while인지 모르고 한방에 빠져나오려면 goto가 현실적으로 편하다는 예기죠.(이건 두번째 글에 있네요.)
또 같은 함수안에서의 goto 문이라면 스파게티코드가 되지 않고도 충분히 직관적인 코드를 작성할수 있으리라 봅니다.(함수하나가 엄청 길면 또 낭패!)

creativeidler의 이미지

goto로 빠져나와야하는 상황은 대체로 return으로 빠져나올 수 있고 그렇게 함수를 구조화시키는 것이 대체로 더 좋은 코드입니다. 그리고 goto와 return의 속도 차이가 중요해지는 경우는 "없다"라고 해도 큰 과장이 아닐 겁니다.

moonzoo의 이미지

goto는 c언어의 절차적 특성을 좀 무시하는 경향이 있습니다.

예를 들어..10층 짜리 건물 ( 전체 소스라고 하면)..

프로그램의 흐름이 1층부터 10층까지.. 순차적으로 이루어 지게 됩니다.

엘리베이터는 각층을 순차적으로 1번만 방문하게 됩니다.

while loop문은 반복하지 않냐고 하시는 분이 있을지 모르겠지만

어차피 하나의 block구문으로써 하나의 층으로 볼 수 있습니다.
(하나의 층이 내부적로는 여러층으로 나누어질 수 있겠죠..)

이런식으로 프로그램이 흘러가기에 그 흐름이 직관적입니다..

반면에 goto문은 3층까지 올라가던 엘리베이터가 갑자기 7층에 갔다가

어느 순간 2층에 다시 와있게 할 수 있는 등.. 순간이동을 해버리기에 --;

이용하기는 무지 편합니다만.. 불확실성이 증가하겠죠.

다중 루프를 탈출하기 위하여 다중루프 직후로 탈출하는 것은 애교로 봐줄 수

있지만.. 그같은 경우에도 각 루프에 조건만 명확히 주어진다면..

한번의 break만으로도 충분합니다.

결론적으로 goto의 사용은 프로그램의 전체 구조와 흐름에 있어서 유용치

않다고 생각합니다.

paul의 이미지

goto를 분기하는데 사용하는것이 일반적이지만.. 약간 모양새를 달리하면
label, goto를 사용해서 재사용은 불가능하지만 그럭저럭 함수형태를 만들수 있습니다.
어떤 언어에선 예외처리로 사용하기도 하더군요..

예전에 베이직 언어나.. 코볼같은 경우, goto만으로 프로그램이 만들어질만큼 goto의 의존성이 높았더군요. 21세기에 살면서 19세기때 만든것 같은 코볼 소스를 본 적이 있습니다. ;;

그때는 소프트웨어 공학적 측면에서나 언어의 수준등이 지금보다 한참 뒤떨어졌을때가 아닌가 싶은데.. 요즘엔 goto를 쓸 이유는 전혀 없어 보입니다.
적어도 새로 개발되는 프로그램에선 말이죠..
하지만 기존에 잘 돌아가던 프로그램이 goto로 도배 되어있다면 전 그 방식을 그대로 따를 겁니다. -_-

ironiris의 이미지

moonzoo wrote:
goto는 c언어의 절차적 특성을 좀 무시하는 경향이 있습니다.

예를 들어..10층 짜리 건물 ( 전체 소스라고 하면)..

프로그램의 흐름이 1층부터 10층까지.. 순차적으로 이루어 지게 됩니다.

엘리베이터는 각층을 순차적으로 1번만 방문하게 됩니다.

while loop문은 반복하지 않냐고 하시는 분이 있을지 모르겠지만

어차피 하나의 block구문으로써 하나의 층으로 볼 수 있습니다.
(하나의 층이 내부적로는 여러층으로 나누어질 수 있겠죠..)

이런식으로 프로그램이 흘러가기에 그 흐름이 직관적입니다..

반면에 goto문은 3층까지 올라가던 엘리베이터가 갑자기 7층에 갔다가

어느 순간 2층에 다시 와있게 할 수 있는 등.. 순간이동을 해버리기에 --;

이용하기는 무지 편합니다만.. 불확실성이 증가하겠죠.

다중 루프를 탈출하기 위하여 다중루프 직후로 탈출하는 것은 애교로 봐줄 수

있지만.. 그같은 경우에도 각 루프에 조건만 명확히 주어진다면..

한번의 break만으로도 충분합니다.

결론적으로 goto의 사용은 프로그램의 전체 구조와 흐름에 있어서 유용치

않다고 생각합니다.

같은 건물의 엘리베이터에서 순간이동하는 것은 분명히 프로그래머가 의도한 부분이기 때문이고 다른 사람들도 그곳에 엘리베이터가 있다는 것을 알고 있기 때문에 목적에 더 적합하다면 goto를 써도 된다고 봅니다.
하지만 A동의 엘리베이터가 B동으로 가면 그야말로 문제겠죠?
alwaysN00b의 이미지

valor wrote:
     if (malloc1 == error)
          goto error1
     if (malloc2 == error)
          goto error2
     if (malloc3 == error)
          goto error3
     Do_Job
     return OK

error3:
     free3
error2:
     free2
error1:
     free1
     return ERROR

단계적으로 resource를 받아서 처리하는 부분에서 중간에 하나의 resource를 얻지 못해서 이전에 받은 resource를 모두 해제해는 경우라면 goto를 쓰는게 가장 좋지않을까 합니다.

데몬같은거 만들때(C 로) 메모리 누수 막기에는 효과적인 코딩이라 생각해 한표 던지고 갑니다.

언제나 시작

죠커의 이미지

Edsger W. Dijkstra 가 goto를 쓰지 말라고 하는 것은 textual index를 잃어버리기 때문이었습니다.

하지만 예외처리같은 것이 프로그램의 로직의 이해에 도움이 되는 것일까요? 별도의 예외처리 형태로 분리시킬 수 있는 언어적인 지원이 있다면이야 몰라도 없다면 goto를 쓰는 것이 나쁘지 않습니다. 이것은 Dijkstra가 말한 textual index의 분실 문제와도 무관하고 실제로 그도 여기에 동의했습니다.

지리즈의 이미지

개인적인 취향의 문제인데요...

물론, goto를 안쓰고, 얼마든지 해결할 수 있습니다.

break를 사용하던가, 혹은 함수의 return 키워드로 빠져나가던가,

메모리같은 경우도 루프가 포함된 함수밖에서 할당한 후
포인터로 인자를 통해 넘겨서, 함수가 돌아올때 해제하는 식으로
해결할 수 있습니다.

다소 작위적이고 무리해보이는 goto 사용이
소스의 가독성에 도움이 되는지는 고민해 보아야 하죠...

소스의 가독성이란 부분은 어느 일부분은
개인의 성향에 따르는 부분이므로, 쉽게 정의내리기 어렵다는 생각입니다.

루프안에, break를 사용한 것이나 return 키워드로 빠져 나간 것이
goto를 쓰는 것과 별반 차이가 없다라고 생각이 드는 사람과,
goto와 label 자체에 익숙하지 않아서...
이게 도대체 뭐하는 키워드야 하는사람이 있다면... 결과는 판이할 수 있다는 생각입니다.

There is no spoon. Neo from the Matrix 1999.

mach337의 이미지

goto 를 사용해서 소스가 간단해진다면 당연히 써야죠...
그러나...무분별한 goto 는 운영체제에서 paging fualt 가 자주 일어나기 때문에..
프로그램의 실행속도가 비교적 느리게 동작할 수 있습니다.

죠커의 이미지

mach337 wrote:
goto 를 사용해서 소스가 간단해진다면 당연히 써야죠...
그러나...무분별한 goto 는 운영체제에서 paging fualt 가 자주 일어나기 때문에..
프로그램의 실행속도가 비교적 느리게 동작할 수 있습니다.

예외처리같은 부분에서 goto를 사용했는데 paging이 자주 일어난다면 그것은 더 이상 예외가 아닐겁니다.

only2sea의 이미지

mach337 wrote:
goto 를 사용해서 소스가 간단해진다면 당연히 써야죠...
그러나...무분별한 goto 는 운영체제에서 paging fualt 가 자주 일어나기 때문에..
프로그램의 실행속도가 비교적 느리게 동작할 수 있습니다.

goto를 쓰거나 다른 control statement를 쓰거나 함수를 쓰거나 모든 경우에 paging fault 문제는 달라질 것이 없습니다. 지금 논의가 코딩 레벨에서 말하는 분, 컴파일된 결과에 대해 논하는 분, 둘 중 아무것도 아닌 분... 크게 이렇게 나눠져 있습니다.

저는 요즘 컴파일러의 발전에 힘입어, goto를 쓴다고 해서 최적화된 코드가 나온다고 생각하지 않습니다. 오히려 경우에 따라 goto가 컴파일러에 의한 최적화된 코드의 생성을 방해할지도 모른다고 생각합니다. 만일 goto를 써서 최적화가 필요하다면 아까 어느 분께서 말씀하신대로 처음부터 goto로 짜는 것보다는 나중에 optimizing을 하는 것이 나을것 같습니다. 그리고 goto 문제에 대해서 논점은 최적화가 극도로 필요한 상황의 문제를 결부시키면 안된다고 생각합니다. 최적화가 극도로 필요한 상황의 문제에서 코딩의 재사용성과 가독성을 함께 논하고 있는데 그런 경우라면 모든거 다 필요 없고 단지 속도만 빨리 나오면 되죠. 거의 하드웨어 레벨의 코드나, 커널 코드 같은 것은 보시면 아시겠지만 최적화를 위해서 코드가 어떤지 보시면 아실 겁니다. 만약 특정 부분을 빠르게 하기 위해서 어셈블리로 작성을 했다면 전혀 70년대 논의되었던 구조적 프로그래밍에도 맞지 않는다고 비난할 수 없죠. 그런 것을 예로 들면서 써도 된다고 하면 논점이 어긋나네요.

좀 비약을 하자면, 인육을 먹어서는 안된다는 논의를 하는데, 식인종은 그렇게 하고, 그 사회에서는 그렇게 하지않으면 곤란하기 때문에 우리 사회에서도 된다고 주장하는 것과 비슷하네요.

결론적으로 제 생각은 대부분의 경우에 goto를 쓰지 않아야 한다고 생각하고, 커널 레벨이나 여타 비슷한 경우에는 이런 코딩 패러다임과는 논외로 해야한다는 것입니다. 고레벨 코딩 패러다임에 대한 논의에서 로우레벨 케이스를 적용하지 않았으면 합니다.

hys545의 이미지

그런데 c#이나 java에서도 goto를 지원하는데
이건 쓰라고 만든거 아닌가여?
쓰지 말라고 하면서 왜 goto는 지원하게 하는지 궁금..

즐린

나는오리의 이미지

hys545 wrote:
그런데 c#이나 java에서도 goto를 지원하는데
이건 쓰라고 만든거 아닌가여?
쓰지 말라고 하면서 왜 goto는 지원하게 하는지 궁금..
goto는 양날의 검입니다.

지금 위의 수많은 사람들이 수많은 이야기를 했지만 결과는 '양날의 검' 하나입니다.
그 외에 다른 결말은 절대 기대할 수 없답니다.

NN의 이미지

비유해보자면, goto는 가벼운 병에 걸렸을 때 먹으면 잘 듣는 약 정도로 생각합니다. 약을 복용하지 않아도 병이 자연치유되지만, 적당한 때 적당히 복용하면 효과를 빨리보는 그런 약 말이죠. 물론 남용하면 건강을 해치게 되니까 정말 필요 할 때 제한적으로만 복용하는것이 원칙이겠죠.

이 경우에도 여러가지 '조언'들이 가능합니다. 어떤 사람은 어차피 자연치유될 수 있는것이니 절대로 약을 먹지 말라라고 얘기할수도 있고, 아니면 정석대로 적당한 때에 적당히 복용하는것은 필요하다던지, 그냥 귀찮으니 아플때마다 복용하는것도 괜찮다라고 한다던지하는등등의 얘기들..

그냥 그 이상의 의미는 없는것 같네요. 위의 사항과 함께 "정말 복용이 필요 할 때"가 언제인지 정도만 숙지하고 있으면, 별로 논란이 될만한꺼리조차 되지 않는다는게 제 생각입니다만, 뭐가 이렇게 goto에 대해 시끄러운지 모르겠습니다. (물론 꼭 이곳사람들만 지칭하는게 아니라 여러곳에서 다소 소모적인 goto사용에 대한 토론이 산발적으로 일어났던것을 알고 이런 얘길 하는겁니다.)

개인적으로 과거 goto사용에 대한 마소의 기사 한편에 많은 사람들이 낚인것 같다는 생각이 드는군요. 다익스트라의 고전을 파헤친건 의미있는 시도였지만, 끝을 명확하게 봉합하지 못한것이 아쉬운 부분입니다.

어쨋든 goto라는것으로 꽤 많은 프로그래머들이 제대로 낚였습니다.

creativeidler의 이미지

Java에는 goto가 reserved되어 있지만 사용할 수는 없습니다.

sjpark의 이미지

break 가 goto 문의 기능을 지원하고 있습니다.

http://nicesj.com

moonzoo의 이미지

저위에 2004년9월24일에

goto 반대론적인 입장에서 썼었던 글이 보이는군요.

goto가 프로그램의 흐름을 흔들 수 있다는 생각에는 변함이 없지만

에러처리등에 있어서 goto + 매크로의 조합은 매우 훌륭했습니다.

for문을 써야 할 곳에, while문을 써야 할 곳에, switch문을 써야 할 곳에

뜬끔없이 나타나는 goto문은, 프로그램의 제어흐름을

해치는 안좋은 습관임이 분명하지만.

goto를 써서 좀더 직관적이고 간결한 코드를 만들수 있는데도.

단지 goto를 다른것으로 "대체가능하기 때문에", 안써야 한다는것은

논리에 맞지 않다고 봅니다.

htna의 이미지

mach337 wrote:
goto 를 사용해서 소스가 간단해진다면 당연히 써야죠...
그러나...무분별한 goto 는 운영체제에서 paging fualt 가 자주 일어나기 때문에..
프로그램의 실행속도가 비교적 느리게 동작할 수 있습니다.

어떤점에서 그런것인지 근거를 좀 알고 싶습니다.
goto를 사용하면 page fault가 많아진다는 근거가 있나요?
제가 잘 몰라서리.. ^^;;;

WOW Wow!!!
Computer Science is no more about computers than astronomy is about telescopes.
-- E. W. Dijkstra

ed.netdiver의 이미지

요지는 local scope에서의 사용 정도는 좋을수도 있다로 이해됩니다만...
page fault까지는 모르겠는데, cache hit율을 떨어뜨릴수는 있겠다 싶기는 하네요...^^;

--------------------------------------------------------------------------------
\(´∇`)ノ \(´∇`)ノ \(´∇`)ノ \(´∇`)ノ
def ed():neTdiVeR in range(thEeArTh)

creativeidler의 이미지

Quote:
어떤점에서 그런것인지 근거를 좀 알고 싶습니다.
goto를 사용하면 page fault가 많아진다는 근거가 있나요?
제가 잘 몰라서리.. ^^;;;

막연한 추측은 가능하죠. program의 size가 커서 많은 page를 점유한 상황에서 goto로 이리저리 왔다갔다 하면 많은 page를 access 해야하니까 page fault 확률이 높아지겠죠. 마찬가지로 cache miss도 많아질 수 있구요. 하지만 별다른 통계적인 근거가 없는 이상 "X Window가 C/S 구조니까 느리지!"와 같은 수준의 막연한 추측일 뿐, 신뢰할 만한 근거는 아닙니다. 언제나 profiling 없는 퍼포먼스 논의는 무의미합니다.

게다가 어차피 goto를 method call 같은 걸로 대체한다면 jump가 일어나는 건 똑같기 때문에 goto의 책임인 것도 아니죠.

sjpark의 이미지

예전에 어떤 책인가, BBS에서 인가,

함수는 오직 하나의 입구와 하나의 출구만 있어야 한다

라고 한 기억이 납니다.

중구난방, 여기저기서 return 해 버리는 함수(또는 메소드)를 볼 때,
성질 같아서는 Exit 하나 만들어 주고 그곳으로 goto 해서 점프 시켜 버리고 싶지만,

그 만큼 실행되는 인스트럭션의 수가 많아지고, 자칫 잘모하면, 지저분 해 질 수 있고(가독성)
또,
게다가, 괜히 남의 코드 손댔다가 나중에 책임 따질때,
그 책임 다 나한테 넘어오는게 귀찮고 싫어서 묵과합니다.

어떤 이는 Define macro 에 goto 문 감춰서 코드에만 안보이면 되지 않느냐 라고 주장하는 사람도
제 곁에 있긴 한데.

쓸데 없는 소리 같이 들리더군요. 비록 그 사람 앞에선 말하진 못했죠. 굳이 말해봐야
돌아오는 건, 인간 관계 문제 뿐일테니요..ㅋ

반대로, goto 문 안쓰려고, "변수 하나" 더 선언해서, 변수 값으로 마지막에 return 시키는 건, 그 만큼 쓸데 없는 코드 수행되는 수도 많아 지니, 뭐 개미 코딱지 만큼 걸리는 시간들 무시해도 되지 않느냐
하기도 하겠지만,. 그럼 할말은 없죠.ㅎㅎ (요즘 가독성이 대세! 라고 어디선가 들었는데 말입죠)

어쨋든, 밥 먹고 살면서, 즐기면서 코딩하고 싶으면, goto가 있다는 사실 알고,
필요해질때, 유용하게 잘 써먹으면 되는거 아니겠습니까? ㅎㅎ

굳이 쓰지 말라, 써라, 그럴 필요 없이. 자신 있다면,
잘 쓰면 됩니다.

포크로 찍어 먹든 감아 먹든 뭐든 할 수 있는데 뭐하러 젓가락 쓰냐 라고 하는거랑 비슷하지 않겄어요?
필요하면 포크도 쓰고, 젓가락도 쓰고. 그럼 되죠 머.

주제로 돌아가서
"무조건 goto 는 나쁘다"

"goto, 필요할 때 잘 쓰자"

정도가 괜찮지 않을까 싶습니다.

윗 분 들 중에 이미 비슷한 말을 쓴 분들도 있는거 같네요.

그럼 얼마 남지 않은 주말 여유 잘 보내세요~ :D

http://nicesj.com

예진아씨의 이미지

goto 를 유일하게 써서 이득을 보는 곳은 다중 루프 빠져나가기인데
이에 대한 것도 s모님께서 이미 언급하셨듯 Knuth 할아버지께서 해법을 내놓으셨습니다.
이것은 라인에 레이블을 붙이는 것이 아니라 루프나 블럭에 레이블을 붙이고
break loop1 하면 얼마나 깊이 들어왔든 그냥 loop1 바깥으로 튀어나가는 거죠.
이게 있으면 하면 goto를 쓰는 모든 프로그램과 똑같은 효율을 갖는 프로그램을
goto 없이도 작성할 수 있다는군요. 그러나 이게 있으면 goto 를 쓸 이유가 없습니다.

자바에도 이게 있죠.

이게 지원되지 않는 언어에서 다중루프를 빠져나올 때
실행 속도에 조금도 손해를 보기 싫다면
goto로 빠져나가는 것은 유일하게 허용할 수 있겠죠.

임예진 팬클럽 ♡예진아씨♡ http://cafe.daum.net/imyejin

임예진 팬클럽 ♡예진아씨♡ http://cafe.daum.net/imyejin

lifthrasiir의 이미지

최근의 경험담을 한 번 써 볼까 합니다.

저는 최근 C로 프로그래밍을 많이 하고 있기 때문에 goto를 꽤 많이 사용하는 편입니다. 거의 대부분의 경우 이 goto는 예외 처리때문에 생기는 건데, 대략 다음과 같은 코드에요. (위에서 많이 말한 얘기입니다만...)

handle blah() {
    handle a = NULL, b = NULL, c = NULL;
 
    a = create_handle();
    if (!a) goto error;
    b = create_handle();
    if (!b) goto error;
    c = create_handle();
    if (!c) goto error;
    if (!do_something_with_three_handles(a, b, c)) goto error;
    free_handle(a);
    free_handle(b);
    return c;
 
error:
    if (a) free_handle(a);
    if (b) free_handle(b);
    if (c) free_handle(c);
    return NULL;
}

그러니까... C++ 같은 데서 흔히 말하는 보장인데, 강한 보장(실패했을 경우 시작했을 때와 똑같은 상태로 돌아 온다)을 위해 rollback하는 코드가 있습니다. 이런 류의 코드에서 goto를 안 쓰고 깔끔한 코드가 나오기는 거의 불가능하다고 생각합니다. 위에서는 세 개를 들었습니다만 실제로는 한 함수에 열 개 정도의 서로 다른 종류의 handle이 나올 경우도 있었고, 그것들이 서로 유기적으로 연계되어 있어서 리팩토링하기도 껄끄러웠죠.

다른 예시를 하나 들자면... 한 지인이 이미지 포맷을 해석해야 할 일이 있다고 했는데, 이 이미지 포맷은 한 scanline이 여러 개의 블록으로 나뉘어 있고 한 블록은 n개의 투명 픽셀과 m개의 불투명 픽셀로 구성되어 있는데 투명 픽셀이야 다 똑같으니 갯수만 저장하는 식이라고 합니다. 문제는 이 포맷을 on-the-fly로 스크린 버퍼에 찍어야 하는데 메모리 제한이 심해서 별도의 버퍼를 잡지 않고 클리핑(scanline의 일부분만을 렌더링)을 구현해야 한다고 합니다. 잠시 생각해 보고 다음과 같은 코드(실제로는 좀 더 복잡함)를 짜서 보내 줬습니다.

const char *clip_scanline(const char *ptr, int x1, int x2, int w, char *dest)
{
	int skip = x1, rem = x2 - x1;
	int npixel, ntrans;
	int i;
 
	/* read number of blocks */
	i = *ptr++;
 
	/* skip first x1 pixels */
	while (i--) {
		ntrans = *ptr++;
		if (skip < ntrans) {
			ntrans -= skip;
			goto draw_trans;
		}
		skip -= ntrans;
		npixel = *ptr++;
		if (skip < npixel) {
			ptr += skip;
			npixel -= skip;
			goto draw_pixel;
		}
		ptr += npixel;
		skip -= npixel;
	}
 
	/* draw next (x2-x1) pixels */
	while (i--) {
		ntrans = *ptr++;
	draw_trans: /* ...if left margin ends with transparent pixels */
		if (rem < ntrans) {
			ntrans -= rem;
			goto skip_trans;
		}
		rem -= ntrans;
		ptr += ntrans;
		npixel = *ptr++;
	draw_pixel: /* ...if left margin ends with opaque pixels */
		if (rem < npixel) {
			while (rem--) *dest++ = *ptr++;
			npixel -= rem;
			goto skip_pixel;
		}
		rem -= npixel;
		while (npixel--) *dest++ = *ptr++;
	}
 
	/* ignore remaining pixels */
	while (j--) {
		++ptr;
	skip_trans: /* ...if clip region ends with transparent pixels */
		npixel = *ptr++;
	skip_pixel: /* ...if clip region ends with opaque pixels */
		ptr += npixel;
	}
 
	return ptr;
}

...원래 코드를 줄여서 쓰느라 잘 도는진 모르겠습니다만 대략의 의미는 이해하시리라 믿습니다.

보시듯이 세 개의 state가 존재하는 코드가 되었습니다. (클리핑된 영역 왼쪽을 무시하는 코드, 클리핑된 부분을 그리는 코드, 그 오른쪽을 무시하는 코드) 일반적으로 C에서 FSM은 함수 포인터 등을 사용해서 해결할 수 있지만 이 코드처럼 각 state에 할당된 코드가 짧고 서로 공유하는 데이터가 많을 뿐만 아니라 그 구조가 사실상 순차적이라면 goto가 더 깔끔한 코드를 만들어 낼 수도 있다고 생각합니다. 물론 적절한 주석은 필수겠죠.

lifthrasiir의 이미지

윗글과 중복되어서 지웁니다. -_-;

cppig1995의 이미지

N-queen 문제에서 한 가지 해를 찾는 프로그램을 작성하라는 과제를 받고 귀찮아서 재귀로 짜고 있는데(물론 tail-recursive가 되도록 신중하게) 이중 반복문 안에서 상태 변수를 두고 빠져나가던 것을 goto로 바꾸니 N=1000까지 0.3초에 나오던데요.

역시 다중 반복문 빠져나오는 데는 goto가 최고.

Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.

letsfree의 이미지

§ 햇.살.이.항.상.그.대.의.길.에.빛.나.길.

쓰라고 만들어놓은걸 왜 자꾸 쓰지말라고 하는걸까 ㅠㅠ

§ 햇.살.이.항.상.그.대.의.길.에.빛.나.길.

winterprincess의 이미지

오직 겨울 공주를 위하여.

switch-case문을 사용할 때와 goto를 사용할 때를 나누어서 사용합니다.
switch-case의 경우
config.h에
일반 error숫자를 문자로 define해서 나타냅니다만,
다른 사람이 코드를 볼 때 이해하기 위해서는 config.h를 봐야하는 번거로움이 있더군요.

goto로 할 경우 문자로 직접 사용을 나타낼 수 있어서 다른 사람이 코드를 좀 더 쉽게 볼 수 있다는 장점이 있었습니다.
그래도 개인적으로는 switch-case를 선호할 수 밖에 없더군요.
오래전부터 받아왔던 교육중에 하나가 goto문은 피해라 였으니까요 -_-;;

-----------------------------------------------------------------------------------

오직 겨울 공주를 위하여.

koseph의 이미지

goto 문은 저 역시 사용하지 않은 지가 15년도 넘었습니다.

결정적으로 goto 문을 사용하지 않게 된 동기는 바로 N.S chart 덕분이었습니다.

86년에 처음으로 플로우차트를 배웠는데 템플릿까지 사서..... ㅠㅠ

그해 여름, 갑자기 N.S 차트를 알게 되었습니다.

N.S 차트를 이해하다보면 goto 사용은 엄청나게 줄어듭니다.

그렇다고 아예 쓰지 말라는 건 아닌데요.

아마 goto 문을 어쩌다 쓰는 건 문제가 없겠죠.

하지만, 위에서 말씀하신 스파게티 코드(제 경험상 스파게티 국수 생각보다 잘 엉기지 않습니다^^)라기 보다 라면 코드를 만드시면 곤란합니다.

자기가 짜고도 못 읽을 수준이라면 그건 더이상 유지보수하곤 담 쌓은 절대 하지 말아야 할 것이 되겠죠. 언어가 무엇이든지 간에요.

요즘은 nested if를 너무 복잡하게 써서 정신이 하나도 없게 하는 경우가 더 많은 것 같습니다.

goto 문은 일반 어플리케이션에서는 거의 본적이 없네요.

There's always another way, dear.

---------------------------------
There's always another way, dear.

Flour의 이미지

goto가 꼭 나쁘다기 보다는 양날의 검이 아닐까 생각드는군요.
칼은 편리한 도구이지만 위험하기도하지요....

오호라의 이미지

시대적으로 봤을 때...

구조적 패러다임의 시대!!

순차문, 분기문, 반복문으로 모든게 해결가능하지(?) 않을까란 인식이 점차 확산되는 시대였는데...

GOTO문이 구조적 패러다임의 걸림돌처럼 느끼지 않았을까라고 조심스레 추측해봅니다.

물론 다음 패러다임시대에서는 더욱 극악이죠. 객체지향!! GOTO OUT!!

Hello World.

강예준의 이미지

근데 goto문도 잘쓰면 좋던뎅...

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.